动态点分治,先搞出重心树,对于重心树的每一个节点维护两个队q1,q2,前者维护当前子树到父重心(重心树中的父亲???)的距离,后者维护当前节点每一个出度的q1堆顶,再全局维护一个ans,即所有节点q2的最大值和次大值……
被坑点:
1、一开始求出第一个重心后,dfs要从重心开始搜!!!
2、 dep[x]+dep[y]-2*dep[lca(x,y)];注意要
∗2
!!!
3、开anc数组要开大一点!!!不然就会越界!!!本来开了17,后来发现循环时从17开始扫……
4、乱压行会死得很惨!!!注意优先级!!!
//http://www.cnblogs.com/juruolty/p/6502677.html
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#define maxn 100000+10
#define read(x) scanf("%d",&x)
using namespace std;
int i,j,dep[maxn],rot,c,now_sz,f[maxn],a[maxn],x,T,y,off_tot,n,m,head[maxn];
int anc[maxn][20],g[maxn]={9999999999},sz[maxn],vis[maxn];
char s[10];
struct xx{
int v,next;
}b[maxn<<1];
struct heap{
priority_queue<int> ad,del;
void _push(int x){ad.push(x);};
void _pop(int x){del.push(x);};
int _top(){while (del.size()&&ad.top()==del.top()) ad.pop(),del.pop();return ad.top();}
int get_two(){int a,b;return a=_top(),ad.pop(),b=_top(),_push(a),a+b;}
int sz(){return ad.size()-del.size();}
}ans,q1[maxn],q2[maxn];//q1表示子树节点到父重心距离,
//q2表示子节点q1堆顶,
//ans表示所有重心q2堆顶
void add(int u,int v)
{
b[++m]=(xx){v,head[u]};
head[u]=m;
}
int lca(int p,int q)
{
if (dep[p]<dep[q])swap(p,q);
for (int i=17;i>=0;--i)
if (dep[p]-(1<<i)>=dep[q]) p=anc[p][i];
if (p==q) return p;
for (int i=17;i>=0;--i)
if (anc[p][i]^anc[q][i]) p=anc[p][i],q=anc[q][i];
return anc[p][0];
}
int ds(int x,int y)
{
return dep[x]+dep[y]-2*dep[lca(x,y)];
}
int cal(int x)//turn_off x
{
int u=x;
if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
q2[x]._push(0);
if (q2[x].sz()>=2) ans._push(q2[x].get_two());
while (f[u])
{
if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
if (q1[u].sz()) q2[f[u]]._pop(q1[u]._top());
q1[u]._push(ds(f[u],x));
q2[f[u]]._push(q1[u]._top());
if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
u=f[u];
}
}
int cal2(int x)//turn_on x
{
int u=x;
if (q2[x].sz()>=2) ans._pop(q2[x].get_two());
q2[x]._pop(0);
if (q2[x].sz()>=2) ans._push(q2[x].get_two());
while (f[u])
{
if (q2[f[u]].sz()>=2) ans._pop(q2[f[u]].get_two());
q2[f[u]]._pop(q1[u]._top());
q1[u]._pop(ds(f[u],x));
if (q1[u].sz()) q2[f[u]]._push(q1[u]._top());
if (q2[f[u]].sz()>=2) ans._push(q2[f[u]].get_two());
u=f[u];
}
}
void get_rot(int x,int fa)
{
sz[x]=1;g[x]=0;
for (int i=head[x];i;i=b[i].next)
{
int v=b[i].v;
if (v==fa||vis[v]) continue;
get_rot(v,x);
sz[x]+=sz[v];
g[x]=max(g[x],sz[v]);
}
g[x]=max(g[x],now_sz-sz[x]);
rot=g[x]<g[rot]?x:rot;
}
void build(int x)
{
vis[x]=1;
for (int i=head[x];i;i=b[i].next)
{
int v=b[i].v;
if (vis[v]) continue;
rot=0;now_sz=sz[v];
get_rot(v,0);
f[rot]=x;
build(rot);
}
}
void dfs(int x,int fa)
{
for (int i=head[x];i;i=b[i].next)
{
int v=b[i].v;
if (v==fa) continue;
dep[v]=dep[x]+1;
anc[v][0]=x;
dfs(v,x);
}
}
int main()
{
read(n);
for ( i=1;i<n;++i)
read(x),read(y),add(x,y),add(y,x);
now_sz=n,rot=0,get_rot(1,0),dep[rot]=1,dfs(rot,0),build(rot);
for ( j=1;j<17;++j)
for ( i=1;i<=n;++i)
anc[i][j]=anc[anc[i][j-1]][j-1];
for ( i=1;i<=n;++i) cal(i);
read(T);
off_tot=n;
while (T--)
scanf("%s",s),s[0]=='G'?printf("%d\n",off_tot<=1?off_tot-1:ans._top()):
(((read(x)),a[x]=a[x]==1?0:1)?(--off_tot,cal2(x)):(++off_tot,cal(x)));
return 0;
}