题目大意
一个有n个节点的树,树的每个节点可能有一个苹果或没有,有两种操作:
Cx 将节点x的权值改变,即如果有一个苹果删掉,否则增加一个苹果。
Qx 询问以节点x为根的子树中有多少个苹果。
思路
首先了解一下dfs序
对于棵树进行
d
f
s
dfs
dfs 遍历,
并记录每一个点的
d
f
s
dfs
dfs 序号
s
t
[
i
]
st[i]
st[i],
在一个节点的所有儿子都被遍历过后,
记录当前
e
n
[
i
]
en[i]
en[i] 为当前最大
d
f
s
dfs
dfs 序号的节点的
d
f
s
dfs
dfs 序号。
如图:
这样我们将问题转化为了区间操作
Cx 将某一点的权值改变
Qx 询问区间
[
s
t
[
x
]
,
e
n
[
x
]
]
[st[x], en[x]]
[st[x],en[x]] 的和
树状数组可以轻松实现这些操作。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long boss[1000010],ls[1000010],st[1000100],en[1000100],c[1000010],v[1000010];
long long n,x,y,tot,m;
char b;
struct node
{
long long y,next;
}a[1000010];
void ljb(long long x,long long y)
{
a[++tot].y=y;
a[tot].next=ls[x];
ls[x]=tot;
}
void dfs(long long x)
{
tot++;
st[x]=tot;
for(long long i=ls[x]; i; i=a[i].next)
dfs(a[i].y);
en[x]=tot;
}
long long lowbit(long long x)
{
return x&(-x);
}
void query(long long x,long long s)
{
for(; x<=n; x+=lowbit(x))
c[x]+=s;
}
long long find(long long x)
{
long long ans=0;
for(; x; x-=lowbit(x))
ans+=c[x];
return ans;
}
int main()
{
scanf("%lld",&n);
for(long long i=1; i<n; i++)
{
scanf("%lld%lld",&x,&y);
ljb(x,y);
}
tot=0;
dfs(1);
for(long long i=1; i<=n; i++)//苹果上树
{
v[i]=1;
query(st[i],1);
}
scanf("%lld",&m);
for(long long i=1; i<=m; i++)
{
cin>>b;
scanf("%lld",&x);
if(b=='C')
{
if(v[x]==1)
query(st[x],-1); //删
else
query(st[x],1); //加
v[x]=1-v[x];
}
else
cout<<find(en[x])-find(st[x]-1)<<endl;
}
return 0;
}