青出于蓝胜于蓝 (dfs序 + BIT)

传送门


思路:

        首先一眼dfs序,转化成序列问题来解决这是没有问题的

        但是我在如何求徒弟中武功比他高的时候纠结好久。。。其实是我在dfs序中编的号和他给的武功等级让我很混乱了///

        这里就运用了树状数组求逆序对的那种思想,我从武功最高的人开始(等级为1的)先看他徒弟的整个区间内是否为0,为0就代表徒弟武功都没他高,然后在把他对应的编号+1(因为我们是按照武功等级来访问的,所以如果访问师父时不为0,就说明前面访问的有他的徒弟,即武功比他高)

    

#include<bits/stdc++.h>
#define pb push_back
using namespace std;

const int maxn = 1e5+5;
int in[maxn],out[maxn],cnt;
int s[maxn];
int n,p;
vector<int>vt[maxn];
int lowbit(int x)
{
	return x & -x;
}
void add(int x,int num)
{
	while(x < maxn)
	{
		s[x] += num;
		x += lowbit(x);
	}
	return ;
} 

int sum(int x)
{
	int res = 0;
	while(x)
	{
		res += s[x];
		x -= lowbit(x);
	}
	return res;
}
void dfs(int x,int f)
{
	in[x] = ++cnt;
	for(int i = 0;i < vt[x].size();++i)
	{
		int v = vt[x][i];
		if(v == f) continue;
		dfs(v,x);
	}
	out[x] = cnt;
	return ;
}
int main()
{
	while(~scanf("%d %d",&n,&p))
	{
		for(int i = 0;i <= n;++i)
			vt[i].clear();
		for(int i = 1;i < n;++i)
		{
			int u,v;
			scanf("%d %d",&u,&v);
			vt[u].pb(v);
			vt[v].pb(u);
		}
		cnt = 0;
		dfs(p,-1);
		for(int i = 1;i <= n;++i)
		{
			int ans = sum(out[i]) - sum(in[i] - 1);
			printf("%d%c",ans,i == n?'\n':' ');
			add(in[i],1);
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/howardemily/article/details/79763680
BIT