[hdu3887] Counting Offspring

Description

You are given a tree, it’s root is p, and the node is numbered from 1 to n. Now define f(i) as the number of nodes whose number is less than i in all the succeeding nodes of node i. Now we need to calculate f(i) for any possible i.

Input

Multiple cases (no more than 10), for each case:

The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.

Following n-1 lines, each line has two integers, representing an edge in this tree.

The input terminates with two zeros.

Output

For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.

Sample Input

15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0

Sample Output

0 0 0 0 0 1 6 0 3 1 0 0 0 2 0

Source

2011 Multi-University Training Contest 5 - Host by BNU

题意

给一棵\(n\)个节点的树和树的根节点\(p\),定义\(f(i)\)为以\(i\)为根节点的子树中,编号比\(i\)小的节点个数,求所有的\(f(i)\)

题解

\(DFS\)求出\(DFS\)序,再从小到大统计以它为根节点的子树中比它小的节点个数,统计之后再往线段树加点单点更新,因为这样可以保证统计的每一个都比当前的数小

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<vector>
#include<iomanip>
#include<map>
#include<set>
using namespace std;

const int N=250000; 
int n,p,t,t1[N],t2[N],c[N],v[N];
struct edge
{
	int v,nx;
}e[N];
int ne,hd[N];

void Init()
{
	ne=0,t=0;
	for(int i=1;i<=n;++i)
		hd[i]=-1,v[i]=0,c[i]=0;
}

void Build(int u,int v)
{
	++ne,e[ne]=(edge){v,hd[u]},hd[u]=ne;
}

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

void Dfs(int id)
{
	if(v[id]) return;
	v[id]=1,++t,t1[id]=t;
	for(int i=hd[id];i!=-1;i=e[i].nx)
		Dfs(e[i].v);
	t2[id]=t;
} 

int Lowbit(int x)
{
	return x&-x;
}

int Get_sum(int id)
{
	int Res=0;
	for(;id;)
	{
		Res+=c[id],
		id-=Lowbit(id);
	}
	return Res;
}

void Updata(int id,int num)
{
	for(;id<=n;)
	{
		c[id]+=num,
		id+=Lowbit(id);
	}
}

void Get_Ans()
{
	printf("%d",Get_sum(t2[1])-Get_sum(t1[1]-1));
	Updata(t1[1],1);
	for(int i=2;i<=n;++i)
	{
		printf(" %d",Get_sum(t2[i])-Get_sum(t1[i]-1));
		Updata(t1[i],1);
	}
	putchar('\n');
}

int main()
{
	for(scanf("%d%d",&n,&p);n|p;scanf("%d%d",&n,&p))
		Init(),Read(),Dfs(p),Get_Ans();
	return 0;
}
posted @ 2019-12-21 19:36  OItby  阅读(82)  评论(0编辑  收藏  举报