POJ 3321 DFS序+线段树
思路:
先DFS一遍 对于每一个点 找到begin 和end(DFS进的时候的cnt 和出的时候的cnt)
每回修改的时候 改begin上边的权值 查的时候查 [begin,end]
呃 如果我说得不清楚 请看http://blog.csdn.net/zhang20072844/article/details/6703432
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 600500
int n,xx,yy,first[N],next[N],v[N],tot,tree[N*10],begin[N],end[N],cnt,q;
char op[3];
void add(int x,int y){
v[tot]=y,next[tot]=first[x],first[x]=tot++;
}
void dfs(int x,int fa){
begin[x]=++cnt;
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa)
dfs(v[i],x);
end[x]=cnt;
}
void build(int l,int r,int pos){
if(l==r){tree[pos]=1;return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
build(l,mid,lson),build(mid+1,r,rson);
tree[pos]=tree[lson]+tree[rson];
}
void insert(int l,int r,int pos){
if(l==r){tree[pos]=!tree[pos];return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid>=begin[xx])insert(l,mid,lson);
else insert(mid+1,r,rson);
tree[pos]=tree[lson]+tree[rson];
}
int query(int l,int r,int pos){
if(l>=begin[xx]&&r<=end[xx])return tree[pos];
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<begin[xx])return query(mid+1,r,rson);
else if(mid>=end[xx])return query(l,mid,lson);
else return query(l,mid,lson)+query(mid+1,r,rson);
}
int main(){
memset(first,-1,sizeof(first));
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&xx,&yy);
add(xx,yy),add(yy,xx);
}
dfs(1,-1),build(1,cnt,1);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%s%d",op,&xx);
if(op[0]=='C')insert(1,cnt,1);
else printf("%d\n",query(1,cnt,1));
}
}