poj 3321

主要是dfs,只要dfs这一步想到,也就是怎样把问题转化为区间求和,就很容易用树状数组来求解

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn= 100000;
int head[maxn+10],e[maxn+10],num[maxn+10],lim[maxn+10],sumx[maxn+10],vis[maxn+10];
int nextx[maxn+10];
int n,m,tot,tem;
void dfs(int x)//遍历映射每个点,确定每个点的起始在他和终止的点,也就是每个苹果和他这个子树之上的最后一个节点映射后的编号。
{
	num[x]=tem++;
	int i;
	for(i=head[x];i!=-1;i=nextx[i]) dfs(e[i]);
	lim[x]=tem;
}
int lowbit(int x)
{
	return x&(-x);
}
void update(int x)
{
	int i,flag=0;
	if(vis[x])
	{
		vis[x]=0;
		flag=1;
	}
	else vis[x]=1;
	for(i=x;i<=maxn;i+=lowbit(i))
	{
		if(flag) sumx[i]-=1;
		else sumx[i]+=1;
	}
}
int query(int x)
{
	int i,sum=0;
	for(i=x;i>0;i-=lowbit(i)) sum+=sumx[i];
	return sum;
}
int main()
{
	while(cin>>n)
	{
		int i;
		int u,v;
		tot=0;
		memset(head,-1,sizeof(head));
		memset(sumx,0,sizeof(sumx));
		memset(vis,0,sizeof(vis));
		for(i=0;i<n-1;i++)//先把图建起来
		{
			scanf("%d %d",&u,&v);
			e[tot]=v; nextx[tot]=head[u];
			head[u]=tot;
			tot++;
		}
		tem=1;
		dfs(1);
		scanf("%d",&m);
		for(i=1;i<tem;i++) update(num[i]);
		char c;
		for(i=0;i<m;i++)
		{
			getchar();
			scanf("%c %d",&c,&v);
			if(c=='C') update(num[v]);
			else  printf("%d\n",query(lim[v]-1)-query(num[v])+vis[num[v]]);
		}
	}
	return 0;
}


posted @ 2013-01-24 19:20  LJ_COME!!!!!  阅读(143)  评论(0编辑  收藏  举报