码迷,mamicode.com
首页 > Windows程序 > 详细

poj 2763 Housewife Wind

时间:2018-06-12 16:11:40      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:多个   比较   ret   code   两种   链式前向星   ems   init   amp   

题意:

给出一棵树,两种操作:

1.求出a到b的距离;

2.修改某一条边的权值。

思路:

可以用树链刨分(我不会

首先,求a到b的距离,因为有很多组询问,所以必须得用lca解决

ans = dis[a] + dis[b] - 2 * dis[lca(a,b)] dis是这个点到根的距离

修改某一条边的权值这里比较麻烦,因为修改了某一条边的权值之后,可能有很多个点的距离都会被影响,但是暴力修改的话,会tle

所以就想到用dfs序处理,每一个点的dfs序的区间控制这个点以及它的子树上的所有点

当某一条边被修改时,那么这条边所连接的时间戳比较大的点及其它的子树的所有点的这个区间都会被影响,那么就直接修改区间

查询的时候,只需要查询3个点,a , b , lca(a,b),所以这就是树状数组的区间修改,单点查询,不懂话欢迎看我的算法学习中的这部分??

poj毒瘤,所以只能用链式前向星

边数是点数 * 2,又因为这个错误re了无数发??

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6 const int N = 1e5 + 10;
  7 struct edge
  8 {
  9     int v,cost,next;
 10 }e[N * 2];
 11 int n,q,s;
 12 int node[N][3];
 13 int par[N],st[N],en[N],anc[N][30],sum[N],dep[N],head[N];
 14 int clk,cnt;
 15 int c[N];
 16 
 17 void adde(int u,int v,int cost)
 18 {
 19     e[cnt].v = v;
 20     e[cnt].cost = cost;
 21     e[cnt].next = head[u];
 22     head[u] = cnt++;
 23 }
 24 
 25 int lowbit(int x)
 26 {
 27     return x&(-x);
 28 }
 29 
 30 void add(int x,int k)
 31 {
 32     for (int i = x;i <= n;i += lowbit(i)) c[i] += k;
 33 }
 34 
 35 int getsum(int x)
 36 {
 37     int ans = 0;
 38     for (int i = x;i > 0;i -= lowbit(i)) ans += c[i];
 39     return ans;
 40 }
 41 
 42 void dfs(int u,int fa,int dis)
 43 {
 44     sum[u] = dis;
 45     st[u] = ++clk;
 46     par[u] = fa;
 47     dep[u] = dep[fa] + 1;
 48     for (int i = head[u];i;i = e[i].next)
 49     {
 50         edge E = e[i];
 51         int v = E.v;
 52         if (v != fa)
 53         {
 54             dfs(v,u,sum[u] + E.cost);
 55         }
 56     }
 57     en[u] = clk;
 58 }
 59 
 60 void pred(void)
 61 {
 62     dfs(1,0,0);
 63     for (int i = 1;i <= n;i++) anc[i][0] = par[i];
 64     for (int j = 1;j <= 25;j++)
 65     {
 66         for (int i = 1;i <= n;i++)
 67         {
 68             anc[i][j] = anc[anc[i][j-1]][j-1];
 69         }
 70     }
 71 }
 72 
 73 int lca(int x,int y)
 74 {
 75     if (dep[x] < dep[y]) swap(x,y);
 76     int k = dep[x] - dep[y];
 77     for (int i = 0;i <= 25;i++)
 78     {
 79         if (k >> i & 1) x = anc[x][i];
 80     }
 81     if (x == y) return x;
 82     for (int i = 25;i >= 0;i--)
 83     {
 84         if (anc[x][i] != anc[y][i])
 85         {
 86             x = anc[x][i];
 87             y = anc[y][i];
 88         }
 89     }
 90     return par[x];
 91 }
 92 
 93 void init(void)
 94 {
 95     memset(par,0,sizeof(par));
 96     memset(en,0,sizeof(en));
 97     memset(st,0,sizeof(st));
 98     memset(anc,0,sizeof(anc));
 99     memset(c,0,sizeof(c));
100     memset(sum,0,sizeof(sum));
101     memset(dep,0,sizeof(dep));
102     memset(head,0,sizeof(head));
103     memset(e,0,sizeof(e));
104     clk = 0;
105     cnt = 1;
106     
107 }
108 
109 int main()
110 {
111     while (~scanf("%d%d%d",&n,&q,&s))
112     {
113         init();
114         for (int i = 0;i < n - 1;i++)
115         {
116             int x,y,z;
117             scanf("%d%d%d",&x,&y,&z);
118             adde(x,y,z);
119             adde(y,x,z);
120             node[i][0] = x;
121             node[i][1] = y;
122             node[i][2] = z;
123         }
124         pred();
125         while (q--)
126         {
127             int op;
128             scanf("%d",&op);
129             if (op == 0)
130             {
131                 int u;
132                 scanf("%d",&u);
133                 int js = lca(s,u);
134                 int ans = sum[s] + sum[u] - 2 * sum[js];
135                 int tmp = getsum(st[s]) + getsum(st[u]) - getsum(st[js]) * 2;
136                 printf("%d\n",ans + tmp);
137                 s = u;
138             }
139             else
140             {
141                 int id,w;
142                 scanf("%d%d",&id,&w);
143                 id--;
144                 int ch = w - node[id][2];
145                 node[id][2] = w;
146                 int x = node[id][0],y = node[id][1];
147                 if (st[x] < st[y]) x = y;
148                 int l = st[x],r = en[x];
149                 add(l,ch);
150                 add(r+1,-ch);
151             }
152         }
153     }
154     return 0;
155 }

 

poj 2763 Housewife Wind

标签:多个   比较   ret   code   两种   链式前向星   ems   init   amp   

原文地址:https://www.cnblogs.com/kickit/p/9173022.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!