本题最关键的就是dfs序,这跟之前有一道求父节点中的节点个数很像,我们对这个树进行dfs,记录他开始的节点和最终的节点,这样只要在两个点之间做dfs就行了
首先这不会破坏树的结构,其次,他还表示了每个节点间的相对关系,这是一种很常见的树状数组的技巧
本篇代码需要用c++交,如果想用g++,需要把vector的格式改一下,具体原理我也不懂,反正每次交题的时候,最好用c++交,特别是poj的评测机。
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<cstring> #include<map> #include<set> using namespace std; typedef long long ll; const int N=1e5+10; const int inf=0x3f3f3f3f; int st[N]; int ed[N]; int tr[N]; int vis[N]; vector<int> ma[N]; int n; int idx; void dfs(int u){ idx++; st[u]=idx; for(int i=0;i<ma[u].size();i++){ dfs(ma[u][i]); } ed[u]=idx; } int lowbit(int x){ return x&-x; } void add(int x,int c){ int i; for(i=x;i<=n;i+=lowbit(i)){ tr[i]+=c; } } int sum(int x){ int i; int res=0; for(i=x;i;i-=lowbit(i)){ res+=tr[i]; } return res; } int main(){ int i; cin>>n; for(i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); ma[u].push_back(v); } dfs(1); for(i=1;i<=n;i++){ add(st[i],1); vis[i]=1; } int m; cin>>m; while(m--){ char s[N]; scanf("%s",s); if(*s=='C'){ int x; scanf("%d",&x); if(vis[x]){ add(st[x],-1); vis[x]=0; } else{ add(st[x],1); vis[x]=1; } } else{ int x; scanf("%d",&x); printf("%d\n",sum(ed[x])-sum(st[x]-1)); } } }