Description
在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。
Input
第一行包含两个正整数N和M。
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。
Output
包含若干行,对于每个询问输出一行一个正整数表示答案。
Sample Input
1 10 100 1000 10000 100000 1000000 10000000
1 2
1 3
2 4
2 5
3 6
3 7
3 8
0 3 1
Sample Output
HINT
1<=N,M<=100000
1<=u,v,x<=N
1<=value[i],y<=10000
0<=k<=N-1
emmmmm大力点分,对于一个点x,显然每条合法路径必然经过包含x的某个重心,因为点分了,所以任意一个点x,包含他的重心数最多只有logn个,可以暴力枚举
题目要求求长度<=k的,那么显然任意一个重心d,与d距离<= k - dis(d, x)的子孙都可以和x构成<=k的路径并贡献价值,所以对于每一个点开一个树状数组,维护其作为重心时子孙到他的距离为下标的权值和前缀。(emmmmm讲的有点乱,实际上就是求出距离<=i的所有子孙的权值和)
然后就是按照点分的套路,把同一子树两点构成的重复部分减去,这里再用一个树状数组维护,修改的话就把每一个包含他的重心所对应的树状数组修改就好了..
1 /*program by mangoyang*/ 2 #include<bits/stdc++.h> 3 #define INF (0x7f7f7f7f) 4 #define Max(a, b) ((a) > (b) ? (a) : (b)) 5 #define Min(a, b) ((a) < (b) ? (a) : (b)) 6 #define N (102005) 7 typedef long long ll; 8 using namespace std; 9 namespace fast_IO { 10 inline char read() { 11 static const int IN_LEN = 1000000; 12 static char buf[IN_LEN], *s, *t; 13 if (s == t) { 14 t = (s = buf) + fread(buf, 1, IN_LEN, stdin); 15 if (s == t) return -1; 16 } 17 return *s++; 18 } 19 template<class T> 20 inline void read(T &x) { 21 static bool iosig; 22 static char c; 23 for (iosig = false, c = read(); !isdigit(c); c = read()) { 24 if (c == ‘-‘) iosig = true; 25 if (c == -1) return; 26 } 27 for (x = 0; isdigit(c); c = read()) 28 x = ((x + (x << 2)) << 1) + (c ^ ‘0‘); 29 if (iosig) x = -x; 30 } 31 const int OUT_LEN = 10000000; 32 char obuf[OUT_LEN], *ooh = obuf; 33 inline void print(char c) { 34 if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf; 35 *ooh++ = c; 36 } 37 template<class T> 38 inline void print(T x) { 39 static int buf[30], cnt; 40 if (x == 0) { 41 print(‘0‘); 42 } 43 else { 44 if (x < 0) print(‘-‘), x = -x; 45 for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48; 46 while (cnt) print((char)buf[cnt--]); 47 } 48 } 49 inline void flush() { 50 fwrite(obuf, 1, ooh - obuf, stdout); 51 } 52 } 53 using namespace fast_IO; 54 int a[N<<1], b[N<<1], nxt[N<<1], head[N], cnt; 55 int f[N][22], dep[N], vis[N], val[N], prt[N], sz[N]; 56 int rtsize, all, rt, n, m; 57 struct Point{int x, y;}; 58 struct Fenwick{ 59 int len; 60 vector<int> s; vector<Point> tag; 61 inline void modify(int x, int y){ 62 for(x++; x <= len; x += x & -x) s[x] += y; 63 } 64 inline int query(int x){ 65 int ans = 0; 66 if(x > len - 1) x = len - 1; 67 for(x++; x; x -= x & -x) ans += s[x]; return ans; 68 } 69 inline void build(){ 70 len = 5; 71 for(register int i = 0; i < tag.size(); i++) 72 len = Max(tag[i].x + 5, len); s.resize(len + 5); 73 for(register int i = 0; i < tag.size(); i++) modify(tag[i].x, tag[i].y); 74 } 75 }T1[N], T2[N]; 76 inline void add(int x, int y){ 77 a[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt; 78 } 79 inline void dfs(int u, int fa){ 80 dep[u] = dep[fa] + 1, f[u][0] = fa; 81 for(register int p = head[u]; p; p = nxt[p]){ 82 int v = a[p]; 83 if(v != fa) dfs(v, u); 84 } 85 } 86 inline int LCA(int x, int y){ 87 if(dep[x] < dep[y]) swap(x, y); 88 for(register int i = 20; ~i; i--){ 89 if(dep[f[x][i]] >= dep[y]) x = f[x][i]; 90 if(dep[x] == dep[y]) break; 91 } 92 if(x == y) return x; 93 for(register int i = 20; ~i; i--) 94 if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; 95 return f[x][0]; 96 } 97 inline int Dis(int x, int y){ 98 int lca = LCA(x, y); 99 return dep[x] + dep[y] - 2 * dep[lca]; 100 } 101 inline void find(int u, int fa){ 102 int mson = 0; sz[u] = 1; 103 for(register int p = head[u]; p; p = nxt[p]){ 104 int v = a[p]; 105 if(v != fa && !vis[v]){ 106 find(v, u), sz[u] += sz[v]; 107 if(sz[v] > mson) mson = sz[v]; 108 } 109 } 110 mson = Max(mson, all - mson); 111 if(mson <= rtsize) rtsize = mson, rt = u; 112 } 113 inline void change(int u, int fa, int id){ 114 T1[id].tag.push_back((Point){Dis(id, u), val[u]}); 115 if(prt[id]) T2[id].tag.push_back((Point){Dis(u, prt[id]), val[u]}); 116 for(register int p = head[u]; p; p = nxt[p]){ 117 int v = a[p]; 118 if(v != fa && !vis[v]) change(v, u, id); 119 } 120 } 121 inline void build(int u){ 122 vis[u] = 1, change(u, 0, u); 123 for(register int p = head[u]; p; p = nxt[p]){ 124 int v = a[p]; 125 if(!vis[v]){ 126 rtsize = all = sz[v]; 127 find(v, 0), prt[rt] = u, build(rt); 128 } 129 } 130 } 131 inline void modify(int x, int y){ 132 int tmp = y; y = y - val[x], val[x] = tmp; 133 for(register int i = x; i; i = prt[i]){ 134 T1[i].modify(Dis(i, x), y); 135 if(prt[i]) T2[i].modify(Dis(x, prt[i]), y); 136 } 137 } 138 inline int query(int x, int k){ 139 int ans = T1[x].query(k); 140 for(register int i = x; prt[i]; i = prt[i]){ 141 int d = k - Dis(prt[i], x); 142 if(d >= 0) ans += T1[prt[i]].query(d) - T2[i].query(d); 143 } 144 return ans; 145 } 146 int main(){ 147 read(n), read(m); 148 for(register int i = 1; i <= n; i++) read(val[i]); 149 for(register int x, y, i = 1; i < n; i++) 150 read(x), read(y), add(x, y), add(y, x); 151 dfs(1, 0); 152 for(register int j = 1; j <= 20; j++) 153 for(register int i = 1; i <= n; i++) f[i][j] = f[f[i][j-1]][j-1]; 154 rtsize = all = n, find(1, 0); build(rt); 155 for(register int i = 1; i <= n; i++) T1[i].build(), T2[i].build(); 156 int lastans = 0; 157 for(register int i = 1; i <= m; i++){ 158 int op, x, y; 159 read(op), read(x), read(y); 160 x ^= lastans, y ^= lastans; 161 if(op == 1) modify(x, y); 162 if(op == 0) print(lastans = query(x, y)), print(‘\n‘); 163 } 164 flush(); 165 return 0; 166 }