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 }