给出一个苹果树,是一棵树,在每个节点出有一个苹果,然后根节点标号总为1,给出一棵树,上来都有苹果
然后给出一些节点上的操作,操作是进行相反状态有和没有苹果的改变,给出一些询问操作,就是某个节点的子树上所有苹果,包括自己
这题说实话,今天下午耗时最大理解时间最长的题了。。。。
首先用邻接表存储这棵树,然后由于这棵树的节点标号是任意的,所以想到用dfs遍历树一遍后按照访问的次序给树标号,当然也能够求出
某个节点当前的号low[x],和最后一颗字数节点的号high[x],得出一个区间,这个区间上的苹果数就是x节点和子树的苹果数
然后就对一个苹果的新标号进行update这题就解决了。。。。。
有个小问题就是如何判断当前是否有苹果?当前苹果数就 =get(low[x])-get(low[x]-1),还有个办法就是用个标记数组flag来记录每一次的访问,访问一次状态更改一次
#include <stdio.h>
#include <string.h>
#define MAX 100010
struct node
{
int data;
node* next;
};
struct adj
{
node *first;
}list[MAX];
int low[MAX],high[MAX],cnt,c[MAX];
bool visit[MAX];
void dfs(int x)
{
node *l=list[x].first;
cnt++;
low[x]=cnt;
while(l!=NULL)
{
dfs(l->data);
l=l->next;
}
high[x]=cnt;
//printf("i=%d: l=%d h=%d\n",x,low[x],high[x]);
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int flag)
{
while(x<MAX)
{
c[x]+=flag;
x+=lowbit(x);
}
}
int get(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void init()
{
cnt=0;
memset(c,0,sizeof(c));
for(int i=1;i<MAX;i++)
{
list[i].first=NULL;
visit[i]=true;
}
}
int main()
{
int n,m,num,u,v;
node *tmp;
char q[3];
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
tmp=new node;
tmp->data=v;
tmp->next=list[u].first;
list[u].first=tmp;
}
dfs(1);
for(int i=1;i<MAX;i++)
update(i,1);
scanf("%d",&m);
while(m--)
{
scanf("%s%d",q,&num);
//printf("get(%d)=%d get(%d)=%d\n",high[num],get(high[num]),low[num]-1,get(low[num]-1));
if('Q'==q[0])
printf("%d\n",get(high[num])-get(low[num]-1));
else
{
if(get(low[num])-get(low[num]-1)==0)//计算出当前是否有苹果
update(low[num],1);
else
update(low[num],-1);
/* if(visit[num])//这里可用一个标记来判断当前苹果状态,访问一次变一次
update(low[num],-1);
else
update(low[num],1);
visit[num]^=1;*/
}
}
}
}

浙公网安备 33010602011771号