说实话第一眼看成树剖了。
话说树剖+BIT应该能过吧。。。。。吧。。。。
想想还是算了,于是祭出了DFS序(不是欧拉序列)。
以l[i]记录开始访问一个节点的时间,以r[i]记录退出一个节点的时间,于是以i为根的子树的所有l和r的值都在l[i]和r[i]之间了。
然后就可以乱搞(雾)求树上前缀和了(话说这个应不应该叫树上前缀和啊),然后用BIT维护树上前缀和。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; inline int read(){ int x=0;char ch; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } const int N=250000+10; struct Edge{int to,next;}e[N<<1]; int l[N],r[N],ti,head[N],d[N<<1],cnt; void ins(int u,int v){ e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt; } void dfs(int u,int fa){ l[u]=++ti; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==fa)continue; dfs(v,u); } r[u]=++ti; } inline int lowbit(int x){return x&-x;} void add(int x,int v){ for(;x<=ti;x+=lowbit(x))d[x]+=v; } int sum(int x){ int ret=-1; for(;x>0;x-=lowbit(x))ret+=d[x]; return ret; } int main(){ int n,m;n=read();int u,v; for(int i=1;i<n;i++){ u=read();v=read(); ins(u,v);ins(v,u); } dfs(1,0); for(int i=1;i<=n;i++) add(l[i],1),add(r[i],-1); m=read(); char opt[10]; for(int i=1;i<n+m;i++){ scanf("%s",opt); if(opt[0]=='A'){ u=read();v=read(); add(l[v],-1);add(r[v],1); } else printf("%d\n",sum(l[read()])); } return 0; }