http://poj.org/problem?id=3321
给你一颗树,最初每个节点上都有一个苹果,
有两种操作:修改(即修改某一个节点值为0或1)
和查询(查询某一个节点的【子树】上有多少个苹果)
这个在树上跑一遍dfs,得到树的dfs序,每个节点管辖的区间就是in[x] - out[x] 这个区间上的节点都是 节点x的子节点,其中in[x]是x自身
那么接下来的对树的节点修改查询的操作,就变成了对区间的操作了。
修改某个节点,则直接修改其在dfs序的对应节点,
查询某个节点的子树,则直接查询in[x]-out[x]区间即可.
区间查询这里用树状数组
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iostream>
using namespace std;
__int64 inf=15;
double eps=0.000001;
int n,m;
vector < vector<int> > mp(100000+50);
int id;
int in[100000+50],out[100000+50];
int tree[100000+5];
void dfs1(int x)
{
in[x]=++id;
int i;
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
dfs1(v);
}
out[x]=id;
}
int val[100000+50];
int lowbit(int x)
{return x&-x;}
void add(int x,int val)
{
for (int i=x;i<=n;i=i+lowbit(i))
tree[i]+=val;
}
int get(int x)
{
int sum=0,i;
for (i=x;i;i-=lowbit(i))
sum+=tree[i];
return sum;
}
int main()
{
id=0;
int x,y,i;
cin>>n;
for (i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(i,1);
val[i]=1;
mp[x].push_back(y);
}
val[n]=1;
add(n,1);
dfs1(1);
int q,num;
char op;
cin>>q;getchar();
for (i=1;i<=q;i++)
{
scanf("%c %d",&op,&num); getchar();
if (op=='Q')
{
int ans=get(out[num])-get(in[num]-1);
printf("%d\n",ans);
}
else
{
if (val[num])
add(in[num],-1);
else
add(in[num],1);
val[num]=!val[num];
}
}
return 0;
}