HDU-3887-Counting Offspring-dfs序+树状数组

http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=21535


题目大意: 给你一颗n个节点的数,对于每个节点i,问你每个节点的子树中有多少个节点序列数小于i,求f[i]。


先跑一遍dfs,得到dfs序,
树状数组初始化为空
然后我们从 节点编号1遍历到n
对于每个节点编号i,查询 【in[i]-1,out[i]】的sum,便是f[i]
然后我们updata(in[i])的值为1,也就是 在 点i对应dfs序中的位置标1,
下次别的节点y在get_sum时,如果当前点i 在 y节点的管辖范围内,那么 便算作 一个 节点编号小于y的 子节点 

#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];
int vis[100000+50];
void dfs1(int x)
{
	in[x]=++id;
	vis[x]=1;
	
	//	who[id]=x;
	int i;
	for (i=0;i<mp[x].size();i++)
	{
		int v=mp[x][i];
		if (vis[v]) continue;
		dfs1(v);
	}
	out[x]=id;
} 
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() 
{ 
	int x,y,i,rt;
	while(cin>>n>>rt)
	{
		id=0;
		if (!n&&!rt) break;
		memset(tree,0,sizeof(tree)); 
		memset(vis,0,sizeof(vis)); 
		for (i=1;i<=n;i++)
			mp[i].clear(); 
		for (i=1;i<=n-1;i++)
		{
			scanf("%d%d",&x,&y);
			mp[x].push_back(y);
			mp[y].push_back(x);
		}
		dfs1(rt); 
		int line=1;
		for (i=1;i<=n;i++)
		{
			int ret= get(out[i])-get(in[i]-1);
			if (!line) printf(" ");
			printf("%d",ret);
			line=0;
			add(in[i],1);
		}
		printf("\n");
	}
	return 0;
}



你可能感兴趣的:(HDU-3887-Counting Offspring-dfs序+树状数组)