目录:
题意:
给你一颗苹果树,每棵树枝(节点)上都有一个苹果
先给你两个操作
Ca
C
a
表示a点的苹果去掉或者长出来(如果此时没长出来则去掉,如果此时去掉则长出来)
Qa
Q
a
表示询问这棵树上a以及a的所有子节点的苹果个数
分析:
这题需要把一个树形结构变换为线性结构,然后使用树状数组动态求和。变换方法为DFS一次这棵树,记录下每个节点第一次访问和最后一次访问时的顺序编号,这时,在某节点第一次访问和最后一次访问编号之间的访问编号,必定为该节点的子节点,按照访问编号建立树状数组,当改变某一节点苹果时,只需按照该节点第一次访问的编号在树状数组中修改值,查询时统计某节点在第一次访问和最后一次访问编号之间的和。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
int b,e,c;
}x[100001];
struct huangzhenbang{
int u,v,next;
}t[200001];
int first[100001],last[100001],tf[100001],head[100001];
int n;
int lowbit(int x)
{
return x&(-x);
}
void change(int k,int c)
{
while(k<=n)
{
x[k].c+=c;
k+=lowbit(k);
}
}
int sum(int k)
{
int t=0;
while(k>0)
{
t+=x[k].c;
k-=lowbit(k);
}
return t;
}
//以上子程序为树状数组的
int len;
void add(int u,int v)
{
t[++len].u=u;
t[len].v=v;
t[len].next=head[u];
head[u]=len;
t[++len].u=v;
t[len].v=u;
t[len].next=head[v];
head[v]=len;
return;
}
//add为建图
int w=0;
void dfs(int p)
{
tf[p]=1;
first[p]=++w;
for(int i=head[p];i!=0;i=t[i].next)
{
if(tf[t[i].v]==0)
dfs(t[i].v);
}
last[p]=w;
return;
}
//dfs用来求出每个节点的第一次访问和最后一次访问编号
int num[100001];
int main()
{
n=read();
int a,b;
for(int i=1;i<n;i++)
{
a=read();b=read();
add(a,b);//建图(双向)
}
dfs(1);
for(int i=1;i<=n;i++)
change(first[i],1);//先初始化树状数组
int m=read();char ch;
for(int i=1;i<=m;i++)
{
cin>>ch>>b;
if(ch=='C')
{
if(num[first[b]]%2==0)//通过统计次数来判断当前是有还是无
change(first[b],-1);
else change(first[b],1);
num[first[b]]++;//次数+1
}
else
{
int ans=sum(last[b]);
if(first[b]>1)
ans-=sum(first[b]-1);
//求first~last,就用1~last减去1~(first-1)
printf("%d\n",ans);
}
}
return 0;
}