1. 程式人生 > >【BZOJ3730】震波 - 動態點分治

【BZOJ3730】震波 - 動態點分治

code inpu 通過 next sin 其中 分治 n-1 print

題意:

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】震波 - 動態點分治