/* 很容易发现这题用线段树来做 树形结构稍微处理一下就可以变为线性结构,dfs跑一遍将树中的结点重新编号,对于每个节点,当访问完子树之后,将子树的最大节点也保存,这样就能得到一个区间段,于是乎,每棵子树的编号就都变成连续的(读入时的标号与线段树中实际标号不一样,所以先用一个pre数组来记录原来的标号),剩下的就可以套用线段树或者是树状数组的模板了,当查询某个结点时查询所对应的连续区间就可以了 */ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define maxn 100010 struct node{ int lef, rig, id; }tree[maxn]; int root[maxn]; int n, q, v; struct E{ int v, next; }edge[maxn]; int pre[maxn], apple[maxn]; struct SEG{ int lef, rig, mid, ans; }seg[maxn*4]; void dfs(int pp) { tree[pp].lef = v; for(int i= pre[pp]; i!= -1; i= edge[i].next) dfs(edge[i].v); root[pp] = v; tree[pp].rig = v++; } void maketree(int num, int lef, int rig) { seg[num].lef = lef; seg[num].rig = rig; seg[num].mid = (lef + rig) >> 1; seg[num].ans = rig - lef + 1; if( lef != rig) { maketree(num*2, lef, seg[num].mid); maketree(num*2+1, seg[num].mid+1, rig); } } int cal( int num, int lef, int rig) { if( seg[num].lef == lef && seg[num].rig == rig) return seg[num].ans; if( rig <= seg[num].mid) return cal( num*2, lef, rig); else if( lef > seg[num].mid) return cal( num*2+1 , lef, rig); else return cal( num*2, lef , seg[num].mid) + cal(num*2+1, seg[num].mid+1, rig); } void insert( int num, int lef, int val) { seg[num].ans += val; if( seg[num].lef == seg[num].rig) return; if( lef <= seg[num].mid) insert( num*2, lef, val); else if( lef > seg[num].mid) insert( num*2+1, lef, val); } void init() { int aa, bb, value = 0; memset( pre, -1, sizeof(pre)); for(int i= 1; i<n; i++) { scanf("%d%d", &aa, &bb); edge[value].v = bb; edge[value].next = pre[aa]; pre[aa] = value++; } for(int i= 1; i<= n; i++) apple[i] = 1; } int main() { int aa, bb; char tmp[10]; scanf("%d", &n); init(); v = 1; dfs(1); maketree(1, 1, n); scanf("%d", &q); for(int i= 0; i<q; i++) { scanf("%s%d", tmp, &aa); if( tmp[0] == 'Q') printf("%d ", cal(1, tree[aa].lef, tree[aa].rig)); else { if( apple[root[aa]] == 1) bb = -1; else bb = 1; insert( 1, root[aa], bb); apple[root[aa]] = 1 - apple[root[aa]]; } } return 0; }