点分树BZOJ3730 震波

Posted mangoyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了点分树BZOJ3730 震波相关的知识,希望对你有一定的参考价值。

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 震波的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj3730: 震波

BZOJ3730震波(动态点分治)

bzoj3730:震波

P6329 模板点分树 | 震波

P6329 模板点分树 | 震波

bzoj3730 震波