题目:http://poj.org/problem?id=3321
题意:给出一个苹果树,开始每个节点都有一个苹果,有2个操作
C:有苹果就吃掉,没有就会长出一个苹果
Q:查询包括x的子树上苹果的个数
这个题目的关键就是怎么把它从一颗树转化成一个数组
可以用dfs序重新编号,保存节点所维护的区间,然后用树状数组可以解决了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=1e5+5;
struct p
{
int to,nextt;
};
p a[N*2];
int tot,n;
int f[N],l[N],r[N],bit[N];
bool vis[N];
void addedge(int u,int v)
{
a[tot].to=v;
a[tot].nextt=f[u];
f[u]=tot++;
}
void dfs(int x)
{
tot++;
l[x]=tot;
vis[x]=1;
for(int i=f[x];i!=-1;i=a[i].nextt)
if (!vis[a[i].to])
dfs(a[i].to);
r[x]=tot;
}
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=i&-i;
}
}
int sum(int i)
{
int s=0;
while(i>0)
{
s+=bit[i];
i-=i&-i;
}
return s;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int x,y;
tot=0;
memset(f,-1,sizeof(f));
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
tot=0;
memset(vis,0,sizeof(vis));
dfs(1);
memset(bit,0,sizeof(bit));
for(int i=1;i<=n;i++)
add(i,1);
memset(vis,1,sizeof(vis));
int m;
char c;
scanf("%d",&m);
while(m--)
{
scanf(" %c%d",&c,&x);
if (c=='Q')
printf("%d\n",sum(r[x])-sum(l[x]-1));
else
{
if (vis[x])
{
vis[x]=0;
add(l[x],-1);
}
else
{
vis[x]=1;
add(l[x],1);
}
}
}
}
return 0;
}