题意就是给一棵树,然后有2种操作,一是问以x为根节点的子树有多少苹果,二是更改某点的苹果数量。
做法就是用dfs序把树形结构转化成线性结构也就是区间,然后用线段树维护。先要求出每个点的in和out值,然后就给每个点分配了一个新编号了,就是它的in[i],然后dfs序有个特点就是以x为根节点的子树里的节点的dfs序是连续的,所以in[x]~out[x]就对应着这颗子树的信息,查询的话对in[x]~out[x]区间操作。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)|1
#define fuck(x) cout<<#x<<" "<<x<<endl;
const int maxn=1e5+10;
struct node
{
int u,v,nxt;
}e[maxn<<1];
int head[maxn],in[maxn],out[maxn],order[maxn],sum[maxn<<2],tim;
void pushup(int rt)
{
sum[rt]=sum[ls]+sum[rs];
}
void build(int rt,int L,int R)
{
if(L==R)
{
sum[rt]=1;
return ;
}
int mid=(L+R)>>1;
build(ls,L,mid);
build(rs,mid+1,R);
pushup(rt);
}
void update(int rt,int L,int R,int pos)
{
if(L==R)
{
if(sum[rt])
sum[rt]=0;
else
sum[rt]=1;
return ;
}
int mid=(L+R)>>1;
if(pos<=mid)
update(ls,L,mid,pos);
else
update(rs,mid+1,R,pos);
pushup(rt);
}
int query(int rt,int L,int R,int l,int r)
{
if(l<=L&&r>=R)
{
return sum[rt];
}
int mid=(L+R)>>1,ans=0;
if(r<=mid)
ans=query(ls,L,mid,l,r);
else
if(l>mid)
ans=query(rs,mid+1,R,l,r);
else
ans=query(ls,L,mid,l,r)+query(rs,mid+1,R,l,r);
return ans;
}
void dfs(int now,int fa)
{
in[now]=++tim;
for(int i=head[now];i!=-1;i=e[i].nxt)
{
if(e[i].v==fa) continue;
dfs(e[i].v,now);
}
out[now]=tim;
}
int main()
{
int n,q,cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) head[i]=-1;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;
e[++cnt].u=v;
e[cnt].v=u;
e[cnt].nxt=head[v];
head[v]=cnt;
}
dfs(1,0);
for(int i=1;i<=n;i++) order[in[i]]=i;
build(1,1,n);
scanf("%d",&q);
while(q--)
{
char ch;
int k;
scanf(" %c%d",&ch,&k);
if(ch=='C')
update(1,1,n,in[k]);
else
printf("%d\n",query(1,1,n,in[k],out[k]));
}
return 0;
}