Apple Tree POJ - 3321

41 阅读1分钟

 对树进行DFS,记时间节点cnt初始等于0,每到一个新的节点(之前没有到过的节点),将cnt+1,作为这个节点的开始时刻,等到遍历完以这个节点为根的子树,回到这个节点时,此时的cnt是这个节点的结束时刻,例如下图:

这样就实现了,将节点与节点之间的包含关系,转化到了线段区间上

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;

    #define lowbit(x) (x&(-x))

    const int MAXN=1e5+10;
    int n,u,v,m,cnt,ecnt;
    int tree[MAXN];
    int s[MAXN],e[MAXN],vis[MAXN],ismark[MAXN],edge[MAXN<<1],head[MAXN],nxt[MAXN<<1];


    inline void rebuild(int x)
    {
    	s[x]=++cnt;

    	for(int i=head[x];i!=0;i=nxt[i]){
            int child=edge[i];
    		if(ismark[child]==0)
    		{
    			ismark[child]=1;
    			rebuild(child);
    		}
    	}
    	e[x]=cnt;
    }

    void update(int x,int d)
    {
    	while(x<=cnt)
    	{
    		tree[x]+=d;
    		x+=lowbit(x);
    	}
    }

    int sum(int x)
    {
    	int ans=0;
    	while(x>0)
    	{
    		ans+=tree[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }

    inline void add(int u,int v){
        edge[++ecnt]=v;
        nxt[ecnt]=head[u];
        head[u]=ecnt;
    }

    int main()
    {
    	//freopen("D:\in.txt","r",stdin);

    	scanf("%d",&n);
    	for(int i=1;i<=n-1;i++)
    	{
    		scanf("%d%d",&u,&v);
    		add(u,v);
    		add(v,u);
    	}

    	ismark[1]=1;
    	rebuild(1);

    	for(int i=1;i<=n;i++)
    	{
    		update(s[i],1);
    	}

    	cin>>m;
    	char op;
    	int x;
        memset(vis,0,sizeof(vis));
    	for(int i=1;i<=m;i++)
    	{
    		scanf(" %c%d",&op,&x);
    		if(op=='Q')
    		{
    		    printf("%d\n",sum(e[x])-sum(s[x]-1));
    		}
    		else
    		{
    			if(!vis[x])
    			{
    				update(s[x],-1);
    				vis[x]=1;
    			}
    			else
    			{
    				update(s[x],1);
    				vis[x]=0;
    			}

    		}
    	}

    	return 0;
    }