1. 程式人生 > >BZOJ 1103: [POI2007]大都市meg

BZOJ 1103: [POI2007]大都市meg

etc 解釋 text 單點 %d .com 分享圖片 格式 現在

Description

  在經濟全球化浪潮的影響下,習慣於漫步在清晨的鄉間小路的郵遞員Blue Mary也開始騎著摩托車傳遞郵件了。
不過,她經常回憶起以前在鄉間漫步的情景。昔日,鄉下有依次編號為1..n的n個小村莊,某些村莊之間有一些雙
向的土路。從每個村莊都恰好有一條路徑到達村莊1(即比特堡)。並且,對於每個村莊,它到比特堡的路徑恰好
只經過編號比它的編號小的村莊。另外,對於所有道路而言,它們都不在除村莊以外的其他地點相遇。在這個未開
化的地方,從來沒有過高架橋和地下鐵道。隨著時間的推移,越來越多的土路被改造成了公路。至今,Blue Mary
還清晰地記得最後一條土路被改造為公路的情景。現在,這裏已經沒有土路了——所有的路都成為了公路,而昔日

的村莊已經變成了一個大都市。 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行,每行有兩種格式的若幹信息

,表示按時間先後發生過的n+m-1次事件:若這行為 A a b(a若這行為 W a, 則表示Blue Mary曾經從比特堡送信到
村莊a。

Output

  有m行,每行包含一個整數,表示對應的某次送信時經過的土路數目。

Sample Input

5
1 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

2
1
0
1

HINT

技術分享圖片

Solution:

  

本題翻譯有毒。我解釋一波題意:給定一棵根節點為$1$,$n$個節點的樹,原本每條邊長度為$1$,有$m+n-1$次操作,每次修改一條邊使得邊權為$0$,或者查詢$1$到某個點的距離(邊權和)。

  不難發現,每次修改一條邊(假設是$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