首先对数进行DFS一下,前序优先遍历,这样做的目的是令节点i的子节点的编号组成的集合是一段连续的数,这样在查询的时候就能够用树状数组来查询连续的区间的和
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 100000 + 5;
struct Edge{
int to;
int next;
};
Edge edge[MAX_N*4];
int head[MAX_N], tot;
int N;
int sum[MAX_N], statu[MAX_N];
int st[MAX_N], ed[MAX_N];
int now_id;
void add_edge( int a, int b ){
edge[tot].to = b;
edge[tot].next = head[a];
head[a] = tot++;
}
inline int lowbit( int x ){
return x&-x;
}
int getsum( int x ){
int ans = 0;
while( x > 0 ){
ans += sum[x];
x -= lowbit( x );
}
return ans;
}
void updata( int x, int val ){
while( x <= MAX_N ){
sum[x] += val;
x += lowbit( x );
}
}
void DFS( int x ){
st[x] = ++now_id;
for( int i = head[x]; i != -1; i = edge[i].next ){
int to = edge[i].to;
DFS( to );
}
ed[x] = now_id;
}
int main(){
int M;
while( scanf( "%d", &N ) != EOF ){
memset( head, -1, sizeof( head ) );
for( int i = 1; i < N; i++ ){
int temp1, temp2;
scanf( "%d%d", &temp1, &temp2 );
add_edge( temp1, temp2 );
}
now_id = 0;
DFS( 1 );
for( int i = 1; i <= N; i++ ){
statu[i] = 1;
updata( st[i], 1 );
}
scanf( "%d", &M );
char s[10];
int t;
for( int i = 0; i < M; i++ ){
scanf( "%s%d", s, &t );
if( s[0] == 'Q' ){
int ans = getsum( ed[t] ) - getsum( st[t] - 1 );
printf( "%d\n", ans );
}else{
if( statu[t] == 1 ){
updata( st[t], -1 );
}else{
updata( st[t], 1 );
}
statu[t] ^= 1;
}
}
}
return 0;
}