1. 程式人生 > >【點分樹】BZOJ3730 震波

【點分樹】BZOJ3730 震波

一個 line i++ 樹狀數組 oid pac tdi 在線 git

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

8 1
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

11100101

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 }

【點分樹】BZOJ3730 震波