传送门
括号序列:访问到一个点时,加入’(‘,再加入该点编号,访问完这个点及其子树退出时加入’)’
括号序列有一个神奇的性质:任意两点间的距离即为括号序列中将它们之间可匹配的括号全部消去后,剩下的括号的数量。为什么呢???把序列中可以匹配的括号消去后,剩余的括号肯定是”)))…..)(……(((“这样的。’)’的个数就是x到lca(x,y)的距离,’(‘的个数就是y到lca(x,y)的距离。
用线段树维护括号序列,线段树每个结点维护七个元素:
s1:”(“的个数
s2:”)”的个数
l1:左段括号数量最大值(去除匹配括号的)
r1:右段括号数量最大值
l2:左段”(“个数与”)”个数之差最大值
r2:右段”)”个数与”(“个数之差最大值
ans:该区间内去匹配括号后”(“个数与”)”个数之和的最大值。
#include<bits/stdc++.h>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define root 1,1,tim
using namespace std;
const int maxn=1e5+2,INF=0x3f3f3f3f;
int n,m,mark[maxn],cnt;
struct NODE {
int s1,s2,l1,r1,l2,r2,ans;
inline void f(int rt) {
s1=s2=0;
l1=r1=l2=r2=ans=-INF;
if (rt==-1) s1=1;
else if (rt==-2) s2=1;
else if (mark[rt]==1) l1=r1=l2=r2=ans=0;
//使更新序列中的实点(不是括号的点)为有效操作,否则-0x3f3f3f3f加来加去还是很大的负数。。。
}
inline void pushup(NODE &l,NODE &r) {
s1=r.s1+max(0,l.s1-r.s2),
s2=l.s2+max(0,r.s2-l.s1),
l1=max(l.l1,max(l.s1+l.s2+r.l2,l.s2+r.l1-l.s1)),
r1=max(r.r1,max(r.s1+r.s2+l.r2,r.s1+l.r1-r.s2)),
l2=max(l.l2,r.l2+l.s1-l.s2),
r2=max(r.r2,l.r2+r.s2-r.s1),
ans=max(max(l.ans,r.ans),max(l.r1+r.l2,r.l1+l.r2));
}
}s[maxn*3<<2];
int num[maxn*3],tim=0;
int head[maxn],edge=0,pos[maxn];
struct EDGE {
int v,nxt;
}e[maxn<<1];
inline void adde(int u,int v) {
e[edge].v=v,e[edge].nxt=head[u],head[u]=edge++;
e[edge].v=u,e[edge].nxt=head[v],head[v]=edge++;
}
void dfs(int p,int fa) {
num[++tim]=-1;
pos[num[++tim]=p]=tim;
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
if (v!=fa) dfs(v,p);
}
num[++tim]=-2;
}
void modify(int rt,int l,int r,int p) {
if (l==r) {s[rt].f(num[p]);return ;}
int mid=(l+r)>>1;
if (p<=mid) modify(lson,p);
else modify(rson,p);
s[rt].pushup(s[rt<<1],s[rt<<1|1]);
}
void build(int rt,int l,int r) {
if (l==r) {s[rt].f(num[l]);return ;}
int mid=(l+r)>>1;
build(lson),
build(rson),
s[rt].pushup(s[rt<<1],s[rt<<1|1]);
}
inline int read() {
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
int main() {
// freopen("bzoj 1095.in","r",stdin);
memset(head,-1,sizeof(head));
cnt=n=read();
for (register int i=1;i<=n;++i) mark[i]=1;//black
for (register int i=1;i<n;++i) {
int u=read(),v=read();
adde(u,v);
}
dfs(1,0);
build(root);
m=read();
for (register int i=1;i<=m;++i) {
char ss[2];
scanf("%s",ss);
if (ss[0]=='C') {
int u=read();
cnt+=mark[u]=-mark[u];
modify(root,pos[u]);
}
else {
if (cnt==0) puts("-1");//no black points
else if (cnt==1) puts("0");//only one black point
else printf("%d\n",s[1].ans);//ans has been maintained
}
}
return 0;
}