Apple Tree POJ - 3321

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

Apple Tree POJ - 3321_第1张图片

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

#include
#include
#include
#include
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;
}

你可能感兴趣的:(算法)