我去,传说中的动态点分治入门题,想了我几个小时还是不知道怎么处理让不同子树对父亲节点产生贡献,我的方法无论怎么样都会被同一子树的信息影响,然后Orz了一波 PoPoQQQ,Hzwer大爷,对堆的处理很巧妙!具体的自己yy吧 (不过bzoj过了,spoj上Re了,不知道什么鬼)
/**************************************************************
Problem: 1095
User: Clare
Language: C++
Result: Accepted
Time:7056 ms
Memory:94404 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define N 100010
#define INF 0x3f3f3f3f
int n,Sum,root,ans,total;
struct Edge{
int to,next,value;
}edge[N*2],edge1[2000000];
int head[N],head1[N],tot,tot1;
int size[N],f[N],son[N];
bool done[N],White[N];
char S[5];
struct Heap{
priority_queue<int> A,B;
void Push(int k){A.push(k);}
void Erase(int k){B.push(k);}
void Pop()
{
while(B.size()&&A.top()==B.top())
A.pop(),B.pop();
A.pop();
}
int Top()
{
while(B.size()&&A.top()==B.top())
A.pop(),B.pop();
return !A.size()?0:A.top();
}
int size(){return (int)A.size()-(int)B.size();}
int S_top()
{
if(size()<2)return 0;
int x=Top();Pop();
int y=Top();Push(x);
return y;
}
}Ans,B[N],C[N];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void Addedge1(int u,int v,int w)
{
tot1++;edge1[tot1].next=head1[u];edge1[tot1].to=v;edge1[tot1].value=w;head1[u]=tot1;
}
void Addedge(int u,int v,int w)
{
tot++;edge[tot].next=head[u];edge[tot].to=v;edge[tot].value=w;head[u]=tot;
tot++;edge[tot].next=head[v];edge[tot].to=u;edge[tot].value=w;head[v]=tot;
}
void Get_root(int k,int fa)
{
size[k]=1;f[k]=0;
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa||done[v])
continue;
Get_root(v,k);
size[k]+=size[v];
f[k]=max(f[k],size[v]);
}
f[k]=max(f[k],Sum-f[k]);
if(f[k]<f[root])
root=k;
}
void DFS(int k,int fa,int rt,int d)
{
Addedge1(k,rt,d);
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa||done[v])
continue;
DFS(v,k,rt,d+edge[i].value);
}
}
void Rebuild(int k)
{
done[k]=true;
DFS(k,0,k,0);
for(int i=head[k];i;i=edge[i].next)
{
int v=edge[i].to;
if(done[v])
continue;
root=0;Sum=size[v];
Get_root(v,root);
Rebuild(root);
}
}
void Turn_off(int k)
{
for(int i=head1[k];i;i=edge1[i].next)
{
int pos=edge1[i].to;
if(k==pos)
{
B[pos].Push(0);
if(B[pos].size()==2)Ans.Push(B[pos].Top());
}
int ti=edge1[i].next;
if(!ti)return;
int Fa_pos=edge1[ti].to,tmp=C[pos].Top();
C[pos].Push(edge1[ti].value);
if(edge1[ti].value>tmp)
{
int Max=B[Fa_pos].Top()+B[Fa_pos].S_top(),Size=B[Fa_pos].size();
if(tmp)
B[Fa_pos].Erase(tmp);
B[Fa_pos].Push(edge1[ti].value);
int Now_max=B[Fa_pos].Top()+B[Fa_pos].S_top();
if(Now_max>Max)
{
if(Size>=2)Ans.Erase(Max);
if(B[Fa_pos].size()>=2)Ans.Push(Now_max);
}
}
}
}
void Turn_on(int k)
{
for(int i=head1[k];i;i=edge1[i].next)
{
int pos=edge1[i].to;
if(pos==k)
{
if(B[pos].size()==2)Ans.Erase(B[pos].Top());
B[pos].Erase(0);
}
int ti=edge1[i].next;
if(!ti)return;
int Fa_pos=edge1[ti].to,tmp=C[pos].Top();
C[pos].Erase(edge1[ti].value);
if(edge1[ti].value==tmp)
{
int Max=B[Fa_pos].Top()+B[Fa_pos].S_top(),Size=B[Fa_pos].size();
B[Fa_pos].Erase(tmp);
if(C[pos].Top())
B[Fa_pos].Push(C[pos].Top());
int Now_max=B[Fa_pos].Top()+B[Fa_pos].S_top();
if(Now_max<Max)
{
if(Size>=2)Ans.Erase(Max);
if(B[Fa_pos].size()>=2)Ans.Push(Now_max);
}
}
}
}
int main()
{
n=read();
for(int i=1;i<=n-1;i++)
{
White[i]=true;
int x=read(),y=read();
Addedge(x,y,1);
}
White[n]=true;
Sum=n;f[0]=INF;root=0;
Get_root(1,root);
Rebuild(root);
for(int i=1;i<=n;i++)
C[i].Push(0);
for(int i=1;i<=n;i++)
{
total++;Turn_off(i);
}
int Q=read();
while(Q--)
{
scanf("%s",S);
if(S[0]=='G')
{
if(total==0)
printf("%d\n",-1);
else if(total==1)
printf("%d\n",0);
else printf("%d\n",Ans.Top());
}
else
{
int x=read();
White[x]^=1;
if(!White[x])Turn_on(x),total--;
else Turn_off(x),total++;
}
}
return 0;
}