主要是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;
}