Solution:
我们只需要采用和树链剖分近似的思想——把整个树的dfs序整理出来,排成线型。
这样一个节点的子树肯定是连续的一段,于是乎就可以用树状数组维护单点修改+区间查询的任务了。
#include<iostream>
#include<cstdio>
#define N 100005
using namespace std;
int n,m,tot,first[N],in[N],out[N],sign,tree[N],exist[N];
struct Edge
{
int to,next;
}edge[2*N];
inline void addedge(int x,int y)
{
tot++;
edge[tot].to=y;
edge[tot].next=first[x];
first[x]=tot;
}
inline void dfs(int now,int fa)
{
in[now]=++sign;
for(int u=first[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(vis==fa) continue;
dfs(vis,now);
}
out[now]=sign;
}
inline int lowbit(int x)
{
return x&(-x);
}
inline void update(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i)) tree[i]+=k;
}
inline int query(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i)) ans+=tree[i];
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL);
cin>>n;
for(int i=1;i<=n-1;i++)
{
int x,y;
cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
for(int i=1;i<=n;i++)
{
update(in[i],1);
exist[i]=1;
}
cin>>m;
for(int i=1;i<=m;i++)
{
char ch;
int x;
cin>>ch>>x;
if(ch=='Q')
{
cout<<query(out[x])-query(in[x]-1)<<'\n';
}
if(ch=='C')
{
if(exist[x]) update(in[x],-1);
else update(in[x],1);
exist[x]^=1;
}
}
return 0;
}