正题
题意
有一颗树,开始每个点的值都是1,有两种操作:
1.将一个点的值取反
2.询问一个子树的值的和
解题思路
用后续遍历就可以做到用一个区间代表一棵子树。然后用线段树就好了。
代码
#include<cstdio>
using namespace std;
struct line{int to,next;
}a[100001];
int tot,x,y,num[100001],c[100001],ls[100001],m;
int n,begin[100001],mark[100001];
bool apple[100001];
char cc;
void dfs(int x)
{begin[x]=tot;for (int q=ls[x];q;q=a[q].next){dfs(a[q].to);}mark[x]=++tot;
}//深搜求后序遍历
int lowbit(int x)
{return x&(-x);}
void change(int x,int num)//改变
{int i=x;while(i<=n){c[i]+=num;i+=lowbit(i);}
}
int getsum(int x)//求和
{int sum=0;while (x>0){sum+=c[x];x-=lowbit(x);}return sum;
}
int main()
{scanf("%d",&n);for (int i=1;i<n;i++){scanf("%d%d",&x,&a[i].to);a[i].next=ls[x];ls[x]=i;//插入边change(i,1);//改值}change(n,1);dfs(1);//后序遍历scanf("%d",&m);for (int i=1;i<=m;i++){scanf("\n%c %d",&cc,&x);if (cc=='C'){apple[x]=!apple[x];if (apple[x])change(mark[x],-1);else change(mark[x],1);//该值取反}else{printf("%d\n",getsum(mark[x])-getsum(begin[x]));//输出}}
}