poj3321-Apple Tree-dfs序+树状数组

http://poj.org/problem?id=3321

给你一颗树,最初每个节点上都有一个苹果,

有两种操作:修改(即修改某一个节点值为0或1)

和查询(查询某一个节点的【子树】上有多少个苹果)

 

这个在树上跑一遍dfs,得到树的dfs序,每个节点管辖的区间就是in[x] - out[x] 这个区间上的节点都是 节点x的子节点,其中in[x]是x自身


那么接下来的对树的节点修改查询的操作,就变成了对区间的操作了。


修改某个节点,则直接修改其在dfs序的对应节点,

查询某个节点的子树,则直接查询in[x]-out[x]区间即可. 

区间查询这里用树状数组

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iostream>
using namespace std;  
__int64 inf=15;
double eps=0.000001;    
int  n,m;   
  
vector < vector<int> >  mp(100000+50);
int id;
int in[100000+50],out[100000+50]; 
int tree[100000+5];
void dfs1(int x)
{
	in[x]=++id;
	int i;
	for (i=0;i<mp[x].size();i++)
	{
		int v=mp[x][i];
		 	dfs1(v);
	}
	out[x]=id;
}
int val[100000+50];
int lowbit(int x)
{return x&-x;}
void add(int x,int val)
{
	for (int i=x;i<=n;i=i+lowbit(i))
		tree[i]+=val;
}
int get(int x)
{
	int sum=0,i;
	for (i=x;i;i-=lowbit(i))
		sum+=tree[i];
	return sum;
}
int main() 
{ 
	id=0;
	int x,y,i;
	cin>>n; 
	for (i=1;i<=n-1;i++)
	{
		scanf("%d%d",&x,&y);
		add(i,1);
		val[i]=1;
		mp[x].push_back(y);
	}
	val[n]=1;
	add(n,1);
	dfs1(1);
	int q,num;
	char op;
	cin>>q;getchar();
	for (i=1;i<=q;i++)
	{
		scanf("%c %d",&op,&num); getchar();
		if (op=='Q')
		{
			int ans=get(out[num])-get(in[num]-1);
			printf("%d\n",ans);
		}
		else
		{
			if (val[num])
				add(in[num],-1);
			else
				add(in[num],1);
			val[num]=!val[num];
		}
	}
	return 0;
}


你可能感兴趣的:(poj3321-Apple Tree-dfs序+树状数组)