BZOJ 1103: [POI2007]大都市meg
Description
在經濟全球化浪潮的影響下,習慣於漫步在清晨的鄉間小路的郵遞員Blue Mary也開始騎著摩托車傳遞郵件了。
不過,她經常回憶起以前在鄉間漫步的情景。昔日,鄉下有依次編號為1..n的n個小村莊,某些村莊之間有一些雙
向的土路。從每個村莊都恰好有一條路徑到達村莊1(即比特堡)。並且,對於每個村莊,它到比特堡的路徑恰好
只經過編號比它的編號小的村莊。另外,對於所有道路而言,它們都不在除村莊以外的其他地點相遇。在這個未開
化的地方,從來沒有過高架橋和地下鐵道。隨著時間的推移,越來越多的土路被改造成了公路。至今,Blue Mary
還清晰地記得最後一條土路被改造為公路的情景。現在,這裏已經沒有土路了——所有的路都成為了公路,而昔日
並且在兩次送信經歷的間隔期間,有某些土路被改造成了公路.現在Blue Mary需要你的幫助:計算出每次送信她需
要走過的土路數目。(對於公路,她可以騎摩托車;而對於土路,她就只好推車了。)
Input
第一行是一個數n(1 < = n < = 2 50000).以下n-1行,每行兩個整數a,b(1 < = a以下一行包含一個整數m
(1 < = m < = 2 50000),表示Blue Mary曾經在改造期間送過m次信。以下n+m-1行,每行有兩種格式的若幹信息
村莊a。
Output
有m行,每行包含一個整數,表示對應的某次送信時經過的土路數目。
Sample Input
51 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3
Sample Output
21
0
1
HINT
Solution:
不難發現,每次修改一條邊(假設是$u->v$),到根節點距離會減少的點實際上就是以$v$為根節點的子樹上的所有的點。
於是我們先求出$dfs$序,得到每棵子樹,並統計每個子樹的大小。
然後對$dfs$序離散一下,這樣保證離散後的$dfs$序從小到大排列,使得子樹之間不會有交集,便可以用一棵線段樹維護所有子樹的信息。
那麽每次操作時,就是區間修改和單點查詢了,每次輸出的是所需節點子樹大小$-$單點查詢的值。
代碼:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define lson l,m,rt<<1 4 #define rson m+1,r,rt<<1|1 5 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 6 using namespace std; 7 const int N=250005; 8 int n,dfn[N<<2],ct,cnt,h[N],to[N],net[N],dep[N],tot[N]; 9 int mp[N],add[N<<2],sum[N<<2],p,m; 10 char s[4]; 11 il int gi(){ 12 int a=0;char x=getchar(); 13 while(x<‘0‘||x>‘9‘)x=getchar(); 14 while(x>=‘0‘&&x<=‘9‘)a=(a<<3)+(a<<1)+x-48,x=getchar(); 15 return a; 16 } 17 il void addd(int u,int v){to[++cnt]=v,net[cnt]=h[u],h[u]=cnt;} 18 il void dfs1(int x){ 19 dfn[++ct]=x;tot[x]=1; 20 for(int i=h[x];i;i=net[i])dep[to[i]]=dep[x]+1,dfs1(to[i]),tot[x]+=tot[to[i]]; 21 dfn[++ct]=x; 22 } 23 il void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} 24 il void pushdown(int rt,int k){ 25 if(add[rt]){ 26 add[rt<<1]+=add[rt]; 27 add[rt<<1|1]+=add[rt]; 28 sum[rt<<1]+=add[rt]*(k-(k>>1)); 29 sum[rt<<1|1]+=add[rt]*(k>>1); 30 add[rt]=0; 31 } 32 } 33 il void update(int L,int R,int c,int l,int r,int rt){ 34 if(L<=l&&R>=r){ 35 add[rt]+=c;sum[rt]+=c*(r-l+1); 36 return; 37 } 38 pushdown(rt,r-l+1); 39 int m=l+r>>1; 40 if(L<=m)update(L,R,c,lson); 41 if(m<R)update(L,R,c,rson); 42 pushup(rt); 43 } 44 il int query(int L,int R,int l,int r,int rt){ 45 if(L<=l&&R>=r)return sum[rt]; 46 pushdown(rt,r-l+1); 47 int m=l+r>>1,ret=0; 48 if(L<=m)ret+=query(L,R,lson); 49 if(m<R)ret+=query(L,R,rson); 50 return ret; 51 } 52 int main(){ 53 n=gi(); 54 int u,v; 55 For(i,1,n-1)u=gi(),v=gi(),addd(u,v); 56 dfs1(1); 57 For(i,1,ct) 58 if(!mp[dfn[i]])mp[dfn[i]]=++p,dfn[i]=p; 59 else dfn[i]=mp[dfn[i]]; 60 m=gi()+n-1; 61 while(m--){ 62 scanf("%s",s); 63 if(s[0]==‘W‘){ 64 u=gi(); 65 printf("%d\n",dep[u]-query(mp[u],mp[u],1,n,1)); 66 } 67 else{ 68 u=gi();v=gi(); 69 if(u<v)swap(u,v); 70 update(mp[u],mp[u]+tot[u]-1,1,1,n,1); 71 } 72 } 73 return 0; 74 }
BZOJ 1103: [POI2007]大都市meg