题目链接
测试数据中边是 从上往下给的,也就是从根往叶子给的
大体思路
将树形结构变为线性结构
后序遍历整棵树,记录下遍历这个点的时间和结束遍历的时间,那么[a,b]就可以代表这棵子树。
我们用一个节点的结束时间来标识树状数组中的c[]。即sum(i)表示 所有 遍历结束的时间小于i的节点的权值和
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+2;
int n,m,cnt=1;
struct Edge
{
int u,v,next;
};
struct Apple
{
int l,r;
}apple[maxn];
Edge edge[maxn];
int head[maxn],c[maxn],a[maxn];
void add(int u,int v)///链式前向星
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
inline int lowbit(int x)
{
return x&-x;
}
void dfs(int u)
{
apple[u].l=cnt;
for(int i = head[u];~i;i=edge[i].next)
{
dfs(edge[i].v);
}
apple[u].r=cnt++;
}
int sum(int x)
{
int res=0;
for(int i=x; i > 0; i-=lowbit(i)) {
res+=c[i];
}
return res;
}
void change(int x)
{
if(a[x]) {
for(int i=x; i < cnt ; i+=lowbit(i)) {
c[i]++;
}
}
else {
for(int i=x; i < cnt; i+=lowbit(i)) {
c[i]--;
}
}
}
int main()
{
memset(head,-1,sizeof head);
memset(c,0,sizeof c);
memset(apple,0,sizeof apple);
scanf("%d",&n);
for(int i = 0; i < n-1; ++i) {
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
cnt=1;
dfs(1);
for(int i = 1; i <= n; ++i) {
a[i]=1;
change(i);
}
char str[3];
scanf("%d",&m);
while(m--) {
int op;
scanf("%s%d",str,&op);
if(str[0]=='Q') {
printf("%d\n",sum(apple[op].r)-sum(apple[op].l-1));
}
else {
a[apple[op].r]=1-a[apple[op].r];
change(apple[op].r);
}
}
return 0;
}