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