题意:一开始1-n都有苹果,Q查询以x为根下存在多少。
树状数组+DFS+队列转换
这题纠结了2天,一开始一点思路都没有,看大神都是吧树状数组转换成队列来做
看了好久都不知道怎么转换的,
解决方法:用两个队列,一个是以记录(s,u),s为起点,一个记录s,为终点
用DFS查找一棵分支,记录访问次序,这样就可以转换成树状数组了
#include <cstdio> //参照大神的代码 #include <cstring> using namespace std; #define N 500000 int tree[N],b[N],e[N],head[N]; //b记录DFS访问的次序,e表示当前节点DFS的最后一个节点标号 bool h[N],v[N]; //v[i]表示是否被访问过 int num; struct node { int x,next; }a[N]; inline int lowbit(int x) {return x&-x;} void update(int x,int t) { int n; if(h[t]) {h[t]=false;n=-1;} //false 表示没有 else {h[t]=true;n=1;} while(x<=num) { tree[x]+=n; x+=lowbit(x); } } int getsum(int x) { int ans=0; while(x>0) { ans+=tree[x]; x-=lowbit(x); } return ans; } void dfs(int x) { v[x]=true; b[x]=++num; for(int i=head[x];i!=-1;i=a[i].next) { if(!v[a[i].x]) dfs(a[i].x); } e[x]=num; //printf("%d %d %d\n",x,num,b[x]); } int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { int m=0; memset(tree,0,sizeof(tree)); memset(head,-1,sizeof(head)); for(i=1;i<n;i++) { int s,u; scanf("%d%d",&s,&u); m++; a[m].x=u;a[m].next=head[s];head[s]=m; m++; a[m].x=s;a[m].next=head[u];head[u]=m; } memset(v,false,sizeof(v)); memset(b,0,sizeof(b)); memset(e,0,sizeof(e)); num=0; dfs(1); for(i=1;i<=n;i++) { update(b[i],i); h[i]=true; } char str[10]; int t,mm; scanf("%d",&mm); for(i=1;i<=mm;i++) { scanf("%s%d",str,&t); if(str[0]=='C') update(b[t],t); else printf("%d\n",getsum(e[t])-getsum(b[t]-1)); } } return 0; }