void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

给出一个苹果树,是一棵树,在每个节点出有一个苹果,然后根节点标号总为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;*/
            }
        }
    }
}
posted on 2011-08-03 00:50  void-man  阅读(769)  评论(0)    收藏  举报