POJ2763-Housewife Wind-树上单点修改区间求和

这道题可以树链剖分做。但是最近在给学弟搞数据结构复习了LCA树状数组RMQ

然后就搞了一发LCA+树状数组维护。

dis数组维护当前点到根节点的权值和。则dis(u,v) = dis[u]+dis[v]-2*dis[lca(u,v)]

修改的时候,单点修改影响了该点所有儿子的dis,刚好可以用dfs序定位所有儿子,用树状数组改段求点很方便。

http://blog.csdn.net/q573290534/article/details/6664454 树状数组的三种求和(改点求段,改段求点,改段求段)

http://blog.csdn.net/qwe2434127/article/details/49819975 dfs序题目类型

http://www.cnblogs.com/longdouhzt/archive/2011/10/16/2214034.html LCA题目小节

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 const int maxn = 2e5+100;
  9 
 10 int N,Q,S;
 11 //vector <int> G[maxn];
 12 
 13 struct edge{
 14     int to,next,w;
 15 }e[2*maxn];
 16 
 17 int head[2*maxn],tot;
 18 void add_edge(int u,int v,int w)
 19 {
 20     e[tot].to = v;
 21     e[tot].w = w;
 22     e[tot].next = head[u];
 23     head[u] = tot++;
 24 
 25     e[tot].to = u;
 26     e[tot].w = w;
 27     e[tot].next = head[v];
 28     head[v] = tot++;
 29 }
 30 
 31 int in[maxn],out[maxn],P[2*maxn],fa[maxn][30],dep[maxn],dis[maxn],cnt;
 32 void dfs(int u,int _fa,int _dep,int _dis)
 33 {
 34     in[u] = ++cnt;
 35     P[cnt] = u;
 36     fa[u][0] = _fa;
 37     dis[u] = _dis;
 38     dep[u] = _dep;
 39     for(int i=head[u];~i;i=e[i].next)
 40     {
 41         int v = e[i].to;
 42         if(v == _fa) continue;
 43         dfs(v,u,_dep+1,_dis+e[i].w);
 44     }
 45     out[u] = ++cnt;
 46 }
 47 void debug()
 48 {
 49     printf("in:\t");for(int i=1;i<=N;i++) printf("%d ",in[i]);puts("");
 50     printf("out:\t");for(int i=1;i<=N;i++) printf("%d ",out[i]);puts("");
 51     printf("p:\t");for(int i=1;i<=cnt;i++) printf("%d ",P[i]);puts("");
 52     printf("dis:\t");for(int i=1;i<=N;i++) printf("%d ",dis[i]);puts("");
 53     printf("dep:\t");for(int i=1;i<=N;i++) printf("%d ",dep[i]);puts("");
 54     printf("edge:");for(int i=0;i<tot;i++) printf("\tto:%d w:%d\n",e[i].to,e[i].w);
 55 }
 56 
 57 int initLCA()
 58 {
 59     int m = (int)log(N)/log(2)+1;
 60     for(int k=0;k<m;k++)
 61     {
 62         for(int v=1;v<=N;v++)
 63         {
 64             if(fa[v][k] < 0) {fa[v][k+1] = -1;continue;}
 65             else fa[v][k+1] = fa[fa[v][k]][k];
 66         }
 67     }
 68 }
 69 
 70 int LCA(int u,int v)
 71 {
 72     int m = (int)log(N)/log(2)+1;
 73     if(dep[v] > dep[u]) swap(u,v);
 74     for(int k=0;k<m;k++)
 75     {
 76         if((dep[u]-dep[v])>>k & 1 )
 77             u = fa[u][k];
 78     }
 79     if(u == v) return u;
 80     for(int k=m-1;k>=0;k--)
 81     {
 82         if(fa[u][k] != fa[v][k])
 83         {
 84             u = fa[u][k];
 85             v = fa[v][k];
 86         }
 87     }
 88     return fa[u][0];
 89 }
 90 
 91 int c[2*maxn];
 92 int lowbit(int x) {return x&-x;}
 93 
 94 void init()
 95 {
 96     memset(head,-1,sizeof head);
 97     memset(fa,-1,sizeof fa);
 98     memset(c,0,sizeof c);
 99     memset(in,0,sizeof in);
100     memset(out,0,sizeof out);
101     tot = 0;
102     cnt = 0;
103 }
104 
105 void add(int x,int d)
106 {
107     while(x)
108     {
109         c[x] += d;
110         x -= lowbit(x);
111     }
112 }
113 void add_seg(int l,int r,int d)
114 {
115     add(r,d);
116     add(l-1,-d);
117 }
118 int sum(int x)
119 {
120     int res = 0;
121     //printf("u:%d ",P[x]);
122     while(x <= cnt)
123     {
124         res += c[x];
125         x += lowbit(x);
126     }
127     //printf("res:%d\n",res);
128     return res;
129 }
130 int dist(int x)
131 {
132     if(x == -1) return 0;
133     return sum(in[x]) + dis[x];
134 }
135 int main()
136 {
137     //freopen("input.txt","r",stdin);
138     while(~scanf("%d%d%d",&N,&Q,&S))
139     {
140         init();
141         for(int i=0,u,v,w;i<N-1;i++)
142         {
143             scanf("%d%d%d",&u,&v,&w);
144             add_edge(u,v,w);
145         }
146         dfs(1,-1,1,0);
147         //debug();
148         initLCA();
149         for(int i=0;i<tot;i+=2)
150         {
151             if(dep[e[i].to] < dep[e[i+1].to]) swap(e[i].to,e[i+1].to);
152         }
153         int op;
154         for(int i=0,a,b,c;i<Q;i++)
155         {
156             scanf("%d",&op);
157             if(op == 0)
158             {
159                 scanf("%d",&a);
160                 int lca = LCA(S,a);
161                 //printf("lca:%d\n",lca);
162 
163                 printf("%d\n",dist(S)+dist(a)-2*(dist(lca)));
164                 S = a;
165             }else
166             {
167                 scanf("%d%d",&a,&b);
168                 a--;
169                 int u = e[a*2].to;
170                 int dw = b - (dist(u) - dist(fa[u][0]));
171                 //printf("dw:%d u:%d\n",dw,u);
172                 add_seg(in[u],out[u],dw);
173             }
174         }
175     }
176 }
posted @ 2016-07-28 00:18  Helica  阅读(869)  评论(0编辑  收藏  举报