这题是用树状数组求和,最关键的是如何把每个点与节点对应起来,我使用的方法是先用vector保存每个点与哪些点相邻,然后从节点1开始,往下进行dfs,相当于给每个找到的点一次对应1,2,3.....也就是lef里存的值,然后返回时tot是最远到达的那个点,就用rig存,这样在某一点以下的点就全找到了,我们利用树状数组的模板,求一下两个sum,再一减就可以得到结果。
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int maxn=100005;
vector<vector<int> > a(maxn);
int lef[maxn];
int rig[maxn];
int s[maxn];
int c[maxn];
int tot=1;
int n,m;
void dfs(int now)
{
lef[now]=tot;
int i;
for(i=0;i<a[now].size();i++)
{
tot++;
dfs(a[now][i]);
}
rig[now]=tot;
}
int lowbit(int k)
{
return k&(-k);
}
int sum(int x)
{
int ret = 0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d)
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(lef,0,sizeof(lef));
memset(rig,0,sizeof(rig));
memset(s,0,sizeof(s));
memset(c,0,sizeof(c));
int i,j;
tot=1;
for(i=0;i<=maxn;i++)
a[i].clear();
for(i=0;i<n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
a[u].push_back(v);
}
dfs(1);
for(i=1;i<=n;i++)
{
s[i]=1;
add(i,1);
}
scanf("%d",&m);
for(i=0;i<m;i++)
{
char cq[5];
int cha;
scanf("%s%d",cq,&cha);
if(cq[0]=='Q')
{
int ans=sum(rig[cha])-sum(lef[cha]-1);
printf("%d\n",ans);
}
else if(cq[0]=='C')
{
if(s[cha])
{
s[cha]=0;
add(lef[cha],-1); //注意此处用left[cha]
}
else
{
s[cha]=1;
add(lef[cha],1);
}
}
}
}
return 0;
}