题意:苹果树上有很多枝桠,每个枝桠用1-N的数字标号。有一两种操作,一种是询问每个枝桠上的苹果(包括其子树),一种是改变一个枝桠(有苹果的变没苹果,没苹果的变有苹果)
做法:
参考大神
其中最重要的一个思想是用order 标记每个枝桠,这样一来,只要是在加一个up,down数组,就可以确定一个枝桠的覆盖范围。其实也可以用线段树做的,可是,正在练树状数组...
然后,因为每个节点中的苹果只要一个,所有,树状数组中的元素num[i]=i&(-i),神题,马克....
#include<cstdio>
#include<cstring>
#include<iostream>
#define LMT 100015
#define lowbit(x) x&(-x)
//主要思想,oder
using namespace std;
int up[LMT],down[LMT],num[LMT],next[LMT],order,n,all;
bool have[LMT];
struct line
{
int u,v,next;
}e[LMT<<1];
void insert(int u,int v)
{
e[all].u=u;
e[all].v=v;
e[all].next=next[u];
next[u]=all++;
}
void init(void)
{
memset(num,0,sizeof(num));
memset(up,0,sizeof(up));
memset(down,0,sizeof(down));
memset(have,1,sizeof(have));
memset(next,-1,sizeof(next));
order=1;all=0;
for(int i=0;i<=n+10;i++)num[i]=i&(-i);
}
void dfs(int u,int pre)
{
down[u]=order;//下界
for(int x=next[u];x!=-1;x=e[x].next)
if(e[x].v!=pre)
dfs(e[x].v,u);
up[u]=order++;//上界
}
int sum(int x)
{
int ret=0;
while(x>0)
{
ret+=num[x];
x-=lowbit(x);
}
return ret;
}
void update(int x,int ope)
{
while(x<=n)
{
num[x]+=ope;
x+=lowbit(x);
}
}
int main(void)
{
int x,m;
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
insert(u,v);
insert(v,u);
}
dfs(1,-1);
scanf("%d",&m);
char ord[3];
while(m--)
{
scanf("%s %d",ord,&x);
if(strcmp(ord,"Q")==0)printf("%d\n",sum(up[x])-sum(down[x]-1));
else
{
if(have[x])
update(up[x],-1);
else update(up[x],1);
have[x]^=1;
}
}
return 0;
}