【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。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理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次操作。
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。
$1\leq N,M\leq 100000$
$1\leq u,v,x\leq N$
$1\leq value[i],y\leq 10000$
$0\leq k\leq N-1$
$1\leq u,v,x\leq N$
$1\leq value[i],y\leq 10000$
$0\leq k\leq N-1$
Output
包含若干行,对于每个询问输出一行一个正整数表示答案。
题解:
动态点分治裸题……
今天终于弄清楚动态点分治是啥玩意了……就是用数据结构爬点分树,大致感觉其实跟树链剖分差不多?(依稀记得我貌似还有个紫荆花之恋的大坑?!)
这题用RMQLCA+线段树随便维护一下就好了……
ps:我写的ST表求LCA+线段树跑了1600ms……卡常数の不能……orzlhx树状数组+神秘优化跑了543ms
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std;
10 typedef long long ll;
11 struct edge{
12 int v,next;
13 }a[200001];
14 struct node{
15 int v,ls,rs;
16 }t[20000001];
17 int n,m,op,u,v,x,y,S,rt,ans=0,tot=0,tim=0,cnt=0,num[100001],f[100001],rt1[100001],rt2[100001],head[100001],mx[100001],dep[100001],siz[100001],dfn[100001],st[200001][18],lg[200001];
18 bool used[100001];
19 void add(int u,int v){
20 a[++tot].v=v;
21 a[tot].next=head[u];
22 head[u]=tot;
23 }
24 void updata(int l,int r,int &u,int p,int x){
25 if(!u)u=++cnt;
26 t[u].v+=x;
27 if(l==r)return;
28 int mid=(l+r)/2;
29 if(p<=mid)updata(l,mid,t[u].ls,p,x);
30 else updata(mid+1,r,t[u].rs,p,x);
31 }
32 int query(int l,int r,int u,int p){
33 if(!u)return 0;
34 if(l==r)return t[u].v;
35 int mid=(l+r)/2;
36 if(p<=mid)return query(l,mid,t[u].ls,p);
37 else return query(mid+1,r,t[u].rs,p)+t[t[u].ls].v;
38 }
39 int getdis(int u,int v){
40 int l=dep[u]+dep[v],tmp;
41 u=dfn[u];
42 v=dfn[v];
43 if(u>v)swap(u,v);
44 tmp=lg[v-u+1];
45 return l-min(st[u][tmp],st[v-(1<<tmp)+1][tmp])*2;
46 }
47 void dfs(int u,int fa,int dpt){
48 dfn[u]=++tim;
49 dep[u]=dpt;
50 st[tim][0]=dep[u];
51 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
52 int v=a[tmp].v;
53 if(v!=fa){
54 dfs(v,u,dpt+1);
55 st[++tim][0]=dep[u];
56 }
57 }
58 }
59 void getrt(int u,int fa){
60 siz[u]=1;
61 mx[u]=0;
62 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
63 int v=a[tmp].v;
64 if(v!=fa&&!used[v]){
65 getrt(v,u);
66 siz[u]+=siz[v];
67 mx[u]=max(mx[u],siz[v]);
68 }
69 }
70 mx[u]=max(mx[u],S-mx[u]);
71 if(mx[u]<mx[rt])rt=u;
72 }
73 void getn(int u,int fa,int ls){
74 updata(0,n-1,rt1[ls],getdis(u,ls),num[u]);
75 if(f[ls])updata(0,n-1,rt2[ls],getdis(u,f[ls]),num[u]);
76 siz[u]=1;
77 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
78 int v=a[tmp].v;
79 if(v!=fa&&!used[v]){
80 getn(v,u,ls);
81 siz[u]+=siz[v];
82 }
83 }
84 }
85 void divide(int u){
86 getn(u,0,u);
87 used[u]=true;
88 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
89 int v=a[tmp].v;
90 if(!used[v]){
91 S=siz[v];
92 rt=0;
93 getrt(v,0);
94 f[rt]=u;
95 divide(rt);
96 }
97 }
98 }
99 void LHX_AK_IOI(int u,int k){
100 for(int now=u;now;now=f[now]){
101 updata(0,n-1,rt1[now],getdis(u,now),k-num[u]);
102 if(f[now])updata(0,n-1,rt2[now],getdis(u,f[now]),k-num[u]);
103 }
104 num[u]=k;
105 }
106 int LHX_AK_NOI(int u,int k){
107 int ret=0;
108 for(int now=u;now;now=f[now]){
109 if(getdis(u,now)<=k)ret+=query(0,n-1,rt1[now],k-getdis(u,now));
110 if(f[now]&&getdis(u,f[now])<=k)ret-=query(0,n-1,rt2[now],k-getdis(u,f[now]));
111 }
112 return ret;
113 }
114 int main(){
115 memset(head,-1,sizeof(head));
116 scanf("%d%d",&n,&m);
117 for(int i=1;i<=n;i++)scanf("%d",&num[i]);
118 for(int i=1;i<n;i++){
119 scanf("%d%d",&u,&v);
120 add(u,v);
121 add(v,u);
122 }
123 dfs(1,0,1);
124 lg[0]=-1;
125 for(int i=1;i<=tim;i++)lg[i]=lg[i>>1]+1;
126 for(int i=1;(1<<i)<=tim;i++){
127 for(int j=1;j<=tim-(1<<i)+1;j++){
128 st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
129 }
130 }
131 mx[rt=0]=inf;
132 S=n;
133 getrt(1,0);
134 divide(rt);
135 for(int i=1;i<=m;i++){
136 scanf("%d%d%d",&op,&x,&y);
137 x^=ans,y^=ans;
138 if(op==0){
139 ans=LHX_AK_NOI(x,y);
140 printf("%d\n",ans);
141 }else LHX_AK_IOI(x,y);
142 }
143 return 0;
144 }