【BZOJ3730】震波 - 動態點分治
阿新 • • 發佈:2018-10-27
code inpu 通過 next sin 其中 分治 n-1 print
不幸的是,這片土地常常發生地震,並且隨著時代的發展,城市的價值也往往會發生變動。
接下來你需要在線處理M次操作:
0 x k 表示發生了一次地震,震中城市為x,影響範圍為k,所有與x距離不超過k的城市都將受到影響,該次地震造成的經濟損失為所有受影響城市的價值和。
1 x y 表示第x個城市的價值變成了y。
為了體現程序的在線性,操作中的x、y、k都需要異或你程序上一次的輸出來解密,如果之前沒有輸出,則默認上一次的輸出為0。
第二行包含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$
題意:
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次操作。
$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$
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 }
【BZOJ3730】震波 - 動態點分治