要是你想做这个题,你首先要知道一个基(shen)本(qi)的性质:树上的每个子树的dfs序都是连续的
一个很显然的性质(知道了就不会忘了)
然后就可以做这个题啦
区间和用树状数组简单的维护一下就好
我的代码维护的是这个子树的空节点(就是没有苹果的节点),那么有苹果的节点数目就是(子树大小)-(空节点数)
(轮这个题的坑
(1. 数据范围绝对不止1e5,我开到了1e6才能过,而且数组开小了返回的还是TLE。。。。迷
(2. 这个题卡vector,用vector的可以改用一发其他的姿势了(比如前向星
然后然后感觉其他的也没有什么难想的地方
一个很显然的性质(知道了就不会忘了)
然后就可以做这个题啦
区间和用树状数组简单的维护一下就好
我的代码维护的是这个子树的空节点(就是没有苹果的节点),那么有苹果的节点数目就是(子树大小)-(空节点数)
(轮这个题的坑
(1. 数据范围绝对不止1e5,我开到了1e6才能过,而且数组开小了返回的还是TLE。。。。迷
(2. 这个题卡vector,用vector的可以改用一发其他的姿势了(比如前向星
然后然后感觉其他的也没有什么难想的地方
那么就这样
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1123456;
struct Edge{
int next,to;
}edge[maxn];
int head[maxn],top;
void init(int n){
memset(head,-1,sizeof(head));
top=0;
}
void Link(int st,int ed){
edge[top].to=ed;
edge[top].next=head[st];
head[st]=top++;
}
int siz[maxn],sid[maxn];
int _cnt;
void dfs(int st,int fa){
siz[st]=1,sid[st]=_cnt++;
for(int i = head[st];~i;i=edge[i].next){
int x = edge[i].to;
if(x!=fa){
dfs(x,st);
siz[st]+=siz[x];
}
}
}
void tinit(){
_cnt=1;
dfs(1,0);
}
int sum[maxn],hav[maxn];
void bitinit(){
memset(sum,0,sizeof(sum));
memset(hav,0,sizeof(hav));
}
int lowbit(int x){
return x&(-x);
}
void add(int x,int d,int n){
while(x<=n){
sum[x]+=d;
x+=lowbit(x);
}
}
int que(int x){
int ret = 0;
while(x>0){
ret += sum[x];
x-=lowbit(x);
}
return ret;
}
void update(int x,int n){
int d = hav[x]?-1:1;
hav[x] = d==1;
add(sid[x],d,n);
}
int query(int x){
int val = que(siz[x]+sid[x]-1);
val-=que(sid[x]-1);
return siz[x]-val;
}
int main(){
int n;
while(~scanf("%d",&n)){
int x,y;
init(n);
for(int i=1;i<n;i++){
scanf("%d %d",&x,&y);
Link(x,y);
Link(y,x);
}
tinit();
bitinit();
// for(int i=1;i<=n;i++)
// printf(i<n?"%d ":"%d\n",sid[i]);
// for(int i=1;i<=n;i++)
// printf(i<n?"%d ":"%d\n",siz[i]);
int m;
char ord[10];
scanf("%d",&m);
while(m--){
scanf("%s %d",ord,&x);
if(ord[0]=='C')
update(x,n);
else
printf("%d\n",query(x));
}
}
return 0;
}