捉迷藏 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 }