由于是处理根到节点的信息,dfs序就可以派上用场了,比树链剖分方便多了。
第一次标记为1,第二次为-1,前缀和就是到根经过的路的数量。
#include<bits/stdc++.h>
#define N 250000
using namespace std;
struct Tree{
int l;
int r;
int sum;
};Tree T[8*N+1];
int seq[2*N+1],tim,st[N+1],ed[N+1];
int first[N+1],nex[N+1],to[N+1],siz;
int n,m,x,y;
char opt;
int read()
{
int x=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
return x;
}
void add(int x,int y)
{
nex[siz]=first[x];
first[x]=siz;
to[siz++]=y;
}
void build(int rt,int l,int r)
{
T[rt].l=l,T[rt].r=r;
if(l==r)return;
int mid=(l+r)/2;
build(rt*2,l,mid),build(rt*2+1,mid+1,r);
}
void pushup(int rt)
{
T[rt].sum=T[rt*2].sum+T[rt*2+1].sum;
}
void modify(int rt,int pos,int val)
{
if(T[rt].l==pos&&T[rt].r==pos)
{
T[rt].sum=val;
return;
}
int mid=(T[rt].l+T[rt].r)/2;
if(pos<=mid)modify(rt*2,pos,val);
else modify(rt*2+1,pos,val);
pushup(rt);
}
int qurry(int rt,int l,int r)
{
if(T[rt].l==l&&T[rt].r==r)
return T[rt].sum;
int mid=(T[rt].l+T[rt].r)/2;
if(r<=mid)return qurry(rt*2,l,r);
else if(l>mid)return qurry(rt*2+1,l,r);
else return qurry(rt*2,l,mid)+qurry(rt*2+1,mid+1,r);
}
void DFS(int x)
{
seq[++tim]=x,st[x]=tim;
for(int i=first[x];i!=-1;i=nex[i])
DFS(to[i]);
seq[++tim]=x,ed[x]=tim;
}
int main()
{
memset(first,-1,sizeof(first));
n=read();
for(int i=1;i<n;i++)
{
x=read(),y=read();
if(x>y)swap(x,y);
add(x,y);
}
DFS(1);
build(1,1,tim);
for(int i=1;i<=n;i++)
modify(1,st[i],1),modify(1,ed[i],-1);
m=read();
for(int i=1;i<=n+m-1;i++)
{
opt=getchar();
if(opt=='W')
{
x=read();
printf("%d\n",qurry(1,1,st[x])-1);
}
else
{
x=read(),y=read();
modify(1,st[y],0);
modify(1,ed[y],0);
}
}
return 0;
}