话说第一眼见到以为很简单嘞,自动默认成父亲节点序号>儿子节点序号,以及二叉树,神啊,原谅我的无知吧。
言归正传,本题关键在于如何把多叉树与树状数组结合起来:由于树状数组求的是一段区间里的元素和,所以,要把多叉树对应到线段上,是本题的关键。
如图所示,红色和蓝色的箭头就表示以此结点为根节点的子树,对应的区间和便是子树上的苹果总数。
1.将多叉树转化成区间(需要用到邻接表存树,并用dfs转化)
2.用树状数组求区间和
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #define INF (1<<30) #define MAXN 100010 using namespace std; struct node{ int v; node *p; } *e[MAXN]; void addedge(int a,int b){ node *Node=new node; Node->v=b; Node->p=e[a]; //不知为啥就写成了Node->p=e[b],wa了好久 e[a]=Node; } int ans[MAXN]; int tmp; int n,m; int begin[MAXN],end[MAXN]; bool vis[MAXN]; void dfs(int u,int fa){ tmp++; begin[u]=tmp; for(node *j=e[u];j;j=j->p){ if(j->v==fa) continue; dfs(j->v,u); } end[u]=tmp; } int lowbit(int x){return x&(-x);} void add(int x,int ad){ while(x<=n){ ans[x]+=ad; x+=lowbit(x); } } int getans(int x){ int res=0; while(x){ res+=ans[x]; x-=lowbit(x); } return res; } int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } for(int i=1;i<=n;i++) { vis[i]=1; add(i,1); } tmp=0; dfs(1,0); char str[1]; scanf("%d",&m); while(m--){ int x; scanf("%s%d",str,&x); if(str[0]=='C'){ if(vis[x]){ vis[x]=0; add(begin[x],-1); } else{ vis[x]=1; add(begin[x],1); } } else{ printf("%d\n",getans(end[x])-getans(begin[x]-1)); } } return 0; }