思路:有两种操作,如果结点X有苹果那么拿掉,否则加一个苹果,操作二询问以某个结点为根的子树有多少个苹果,显然一开始给出的树的结点编号是无序的不利于维护,那么可以考虑DFS将结点都重新编号,那么一个子树的结点编号一定是连续的,然后用树状数组维护即可
坑点:会卡STL
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
using namespace std;
const int maxn = 100000+5;
int c[maxn],in[maxn],out[maxn],cnt=0,a[maxn];
struct Edge{int to,next;}e[maxn<<1];
int edges = 0;
int head[maxn];
int lowbit(int x){return x&(-x);}
//vector<int>e[maxn];
void addedge(int u,int v)
{
e[edges].to =v;
e[edges].next = head[u];
head[u]=edges++;
}
void update(int i,int v)
{
while(i<=maxn)
{
c[i]+=v;
i+=lowbit(i);
}
}
int query(int i)
{
int ans = 0;
while(i)
{
ans+=c[i];
i-=lowbit(i);
}
return ans;
}
void dfs(int u,int fa)
{
in[u]=++cnt;
//for(int i = 0;i<e[u].size();i++)
for(int i = head[u];i!=-1;i = e[i].next)
{
int v = e[i].to;
if(v==fa)continue;
dfs(v,u);
}
out[u]=cnt;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
cnt = 0;
edges = 0;
memset(head,-1,sizeof(head));
memset(c,0,sizeof(c));
memset(a,0,sizeof(a));
for(int i = 1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1,-1);
int q;
scanf("%d",&q);
for(int i = 1;i<=n;i++)
update(in[i],1),a[i]=1;
while(q--)
{
char op[2];
int x;
scanf("%s%d",op,&x);
if(op[0]=='Q')
printf("%d\n",query(out[x])-query(in[x]-1));
else if(op[0]=='C')
{
if(a[x])
{
a[x]=0;
update(in[x],-1);
}
else
{
a[x]=1;
update(in[x],1);
}
}
}
}
}