主要是dfs,只要dfs这一步想到,也就是怎样把问题转化为区间求和,就很容易用树状数组来求解
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn= 100000;
int head[maxn+10],e[maxn+10],num[maxn+10],lim[maxn+10],sumx[maxn+10],vis[maxn+10];
int nextx[maxn+10];
int n,m,tot,tem;
void dfs(int x)//遍历映射每个点,确定每个点的起始在他和终止的点,也就是每个苹果和他这个子树之上的最后一个节点映射后的编号。
{
num[x]=tem++;
int i;
for(i=head[x];i!=-1;i=nextx[i]) dfs(e[i]);
lim[x]=tem;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
int i,flag=0;
if(vis[x])
{
vis[x]=0;
flag=1;
}
else vis[x]=1;
for(i=x;i<=maxn;i+=lowbit(i))
{
if(flag) sumx[i]-=1;
else sumx[i]+=1;
}
}
int query(int x)
{
int i,sum=0;
for(i=x;i>0;i-=lowbit(i)) sum+=sumx[i];
return sum;
}
int main()
{
while(cin>>n)
{
int i;
int u,v;
tot=0;
memset(head,-1,sizeof(head));
memset(sumx,0,sizeof(sumx));
memset(vis,0,sizeof(vis));
for(i=0;i<n-1;i++)//先把图建起来
{
scanf("%d %d",&u,&v);
e[tot]=v; nextx[tot]=head[u];
head[u]=tot;
tot++;
}
tem=1;
dfs(1);
scanf("%d",&m);
for(i=1;i<tem;i++) update(num[i]);
char c;
for(i=0;i<m;i++)
{
getchar();
scanf("%c %d",&c,&v);
if(c=='C') update(num[v]);
else printf("%d\n",query(lim[v]-1)-query(num[v])+vis[num[v]]);
}
}
return 0;
}