捉迷藏 Jiajia和Wind是一對恩愛的夫妻,而且他們有不少孩子。某天,Jiajia、Wind和孩子們決定在家裏玩
捉迷藏遊戲。他們的家很大且構造很奇特,由N個屋子和N-1條雙向走廊組成,這N-1條走廊的分佈使得任意兩個屋
子都互相可達。遊戲是這樣進行的,孩子們負責躲藏,Jiajia負責找,而Wind負責操縱這N個屋子的燈。在起初的
時候,全部的燈都沒有被打開。每一次,孩子們只會躲藏在沒有開燈的房間中,可是爲了增長刺激性,孩子們會要
求打開某個房間的電燈或者關閉某個房間的電燈。爲了評估某一次遊戲的複雜性,Jiajia但願知道可能的最遠的兩
個孩子的距離(即最遠的兩個關燈房間的距離)。 咱們將以以下形式定義每一種操做: C(hange) i 改變第i個房
間的照明狀態,若原來打開,則關閉;若原來關閉,則打開。 G(ame) 開始一次遊戲,查詢最遠的兩個關燈房間的
距離。node
第一行包含一個整數N,表示房間的個數,房間將被編號爲1,2,3…N的整數。接下來N-1行每行兩個整數a, b,
表示房間a與房間b之間有一條走廊相連。接下來一行包含一個整數Q,表示操做次數。接着Q行,每行一個操做,如
上文所示。ios
對於每個操做Game,輸出一個非負整數到hide.out,表示最遠的兩個關燈房間的距離。若只有一個房間是關
着燈的,輸出0;若全部房間的燈都開着,輸出-1。數組
1 //Never forget why you start
2 #include<iostream>
3 #include<cstdio>
4 #include<cstdlib>
5 #include<cstring>
6 #include<cmath>
7 #include<algorithm>
8 #include<queue>
9 #define inf (1e9)
10 using namespace std;
11 int n,m;
12 struct node{
13 int next,to;
14 }edge[200005];
15 struct Heap{
16 priority_queue<int>a,b;
17 void clean(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();}
18 void push(int x){a.push(x);}
19 void erase(int x){b.push(x);}
20 void pop(){clean();a.pop();}
21 int top(){clean();if(a.size())return a.top();else return -inf;}
22 int size(){return a.size()-b.size();}
23 int s_top(){
24 if(size()<2)return -inf;
25 clean();
26 int t=a.top(),ret;a.pop();
27 clean();
28 ret=a.top();a.push(t);
29 return ret;
30 }
31 }A[100005],B[100005],C;
32 int head[100005],size;
33 void putin(int from,int to){
34 size++;
35 edge[size].next=head[from];
36 edge[size].to=to;
37 head[from]=size;
38 }
39 int root,tot,f[100005],cnt[100005],depth[100005],vis[100005],fa[100005][20],dis[100005][20];
40 void getroot(int r,int fa){
41 int i;
42 cnt[r]=1;f[r]=0;
43 for(i=head[r];i!=-1;i=edge[i].next){
44 int y=edge[i].to;
45 if(y!=fa&&!vis[y]){
46 getroot(y,r);
47 cnt[r]+=cnt[y];
48 f[r]=max(f[r],cnt[y]);
49 }
50 }
51 f[r]=max(f[r],tot-cnt[r]);
52 if(f[root]>f[r])root=r;
53 }
54 void getship(int r,int tmp,int father,int dep){
55 int i;
56 for(i=head[r];i!=-1;i=edge[i].next){
57 int y=edge[i].to;
58 if(!vis[y]&&y!=father){
59 fa[y][++depth[y]]=tmp;
60 dis[y][depth[y]]=dep;
61 getship(y,tmp,r,dep+1);
62 }
63 }
64 }
65 void buildtree(int r){
66 int i;
67 vis[r]=1;getship(r,r,0,1);int all=tot;
68 for(i=head[r];i!=-1;i=edge[i].next){
69 int y=edge[i].to;
70 if(!vis[y]){
71 if(cnt[y]>cnt[r])cnt[y]=all-cnt[r];tot=cnt[y];
72 root=0;getroot(y,r);buildtree(root);
73 }
74 }
75 }
76 void turn_off(int r){//關掉一盞燈
77 B[r].push(0);//這盞燈能做爲路徑的起點
78 if(B[r].size()==2)C.push(B[r].top());//恰好等於2,說明正好有一條邊
79 for(int i=depth[r];i>1;i--){
80 int t,pre;
81 if(!A[fa[r][i]].size()){//若是A爲空,那麼加入的dis[r][i-1]必定是堆頂
82 A[fa[r][i]].push(dis[r][i-1]);//更新A
83 pre=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top();//記錄當前B對C的貢獻
84 B[fa[r][i-1]].push(dis[r][i-1]);//更新B
85 if(pre>0&&pre==B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top())continue;//若是更新後的B對C的貢獻不變,就continue
86 if(pre>0&&pre!=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top())C.erase(pre),C.push(B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top());
87 //若是更新後的B對C的貢獻改變,就更新C
88 else if(B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top()>0)C.push(B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top());
89 //若是B沒有對C產生貢獻,在加入了這個點以後有產生了貢獻,就直接將貢獻加進去
90 }
91 else{
92 t=A[fa[r][i]].top();
93 A[fa[r][i]].push(dis[r][i-1]);
94 if(t<dis[r][i-1]){
95 pre=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top();
96 B[fa[r][i-1]].erase(t);B[fa[r][i-1]].push(dis[r][i-1]);
97 if(pre>0&&pre!=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top())
98 C.erase(pre),C.push(B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top());
99 }
100 }
101 }
102 }
103 void turn_on(int r){
104 B[r].erase(0);
105 if(B[r].size()==1)C.erase(B[r].top());
106 for(int i=depth[r];i>1;i--){
107 int t,pre;
108 A[fa[r][i]].erase(dis[r][i-1]);
109 if(A[fa[r][i]].top()<dis[r][i-1]){
110 pre=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top();
111 B[fa[r][i-1]].erase(dis[r][i-1]);
112 if(A[fa[r][i]].size())B[fa[r][i-1]].push(A[fa[r][i]].top());
113 if(pre>0&&pre!=B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top()){
114 C.erase(pre);
115 if(B[fa[r][i-1]].size()>=2)
116 C.push(B[fa[r][i-1]].top()+B[fa[r][i-1]].s_top());
117 }
118 }
119 }
120 }
121 int now,on[100005];
122 void change(int x){
123 if(!on[x])turn_on(x);
124 else turn_off(x);
125 on[x]^=1;
126 if(on[x])now++;
127 else now--;
128 }
129 int main(){
130 int i,j;
131 scanf("%d",&n);
132 memset(head,-1,sizeof(head));
133 for(i=1;i<n;i++){
134 int from,to;
135 scanf("%d%d",&from,&to);
136 putin(from,to);
137 putin(to,from);
138 }
139 f[0]=inf;tot=n;getroot(1,0);buildtree(root);
140 for(i=1;i<=n;i++)fa[i][++depth[i]]=i,turn_off(i);
141 scanf("%d",&m);
142 char s[5];
143 while(m--){
144 scanf("%s",s);
145 if(s[0]=='G'){
146 if(now==n)printf("-1\n");
147 else printf("%d\n",max(C.top(),0));
148 }
149 else{
150 scanf("%d",&j);
151 change(j);
152 }
153 }
154 return 0;
155 }