J. 青出于蓝胜于蓝(dfs序+树状数组)

武当派一共有 nnn 人,门派内 nnn 人按照武功高低进行排名,武功最高的人排名第 111,次高的人排名第 222,... 武功最低的人排名第 nnn。现在我们用武功的排名来给每个人标号,除了祖师爷,每个人都有一个师父,每个人可能有多个徒弟。

我们知道,武当派人才辈出,连祖师爷的武功都只能排行到 ppp。也就是说徒弟的武功是可能超过师父的,所谓的青出于蓝胜于蓝。

请你帮忙计算每个人的所有子弟(包括徒弟的徒弟,徒弟的徒弟的徒弟....)中,有多少人的武功超过了他自己。

输入格式

输入第一行两个整数 n,p(1≤n≤100000,1≤p≤n)n, p(1 \le n \le 100000, 1 \le p \le n)n,p(1n100000,1pn)

接下来 n−1n-1n1 行,每行输入两个整数 u,v(1≤u,v≤n)u, v(1 \le u, v \le n)u,v(1u,vn),表示 uuuvvv 之间存在师徒关系。

输出格式

输出一行 nnn 个整数,第 iii 个整数表示武功排行为 iii 的人的子弟有多少人超过了他。

行末不要输出多余的空格

样例输入

10 5
5 3
5 8
3 4
3 1
2 1
6 7
8 7
9 8
8 10

样例输出

0 0 2 0 4 0 1 2 0 0
#include
#include
#include
#define lowbit(x) (x&(-x)) 
typedef long long ll;
using namespace std;
/*
树状数组就是来求前缀和,有忘了,wuwuwu... 
我知道要求dfs序,但是不知道怎么来求一段区间内的小于等于某个值的数量
我们都是从最小值网上走的,我们是按照val,来的,所以直接查询,在【l,r】 
内的数量就可以了,优美 
*/
const int maxn=1e5+10;
int cnt;
int head[maxn*2];
struct Edge{
	int v,nt;
}edge[maxn*2];
void add_edge(int u,int v){
	edge[cnt].nt=head[u];
	edge[cnt].v=v;
	head[u]=cnt++;
}
int l[maxn],r[maxn];

void dfs(int now,int fa,int& id){
	l[now]=++id;//
	for(int i=head[now];i!=-1;i=edge[i].nt){
		int v=edge[i].v;
		if(v==fa) continue;
		dfs(v,now,id);
	}
	r[now]=id;
}

void print(int n){
	for(int i=1;i<=n;i++){
		printf("i:%d %d %d\n",i,l[i],r[i]);
	}
}
int n;
int tr[maxn];
int get_sum(int x){
	int sum=0;
	while(x>0){
		sum+=tr[x];
		x-=lowbit(x);
	}
	return sum;
}

void update(int x,int val){
	while(x<=n){
		tr[x]+=val;
		x+=lowbit(x);
	}
}
int ans[maxn];

int main(){
	cnt=0;
	memset(head,-1,sizeof(head));
	int rt;
	scanf("%d %d",&n,&rt);
	for(int i=1;i

你可能感兴趣的:(....dfs序,.....树状数组)