思路:建立dfs序后,利用树状数组(或线段树)先把当前名次所在区间加+1,然后求dfs序区间值的差,即答案。
#include <iostream> #include <cmath> #include <cctype> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> #include <queue> #include <map> //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int MAXN = 200005; typedef long long LL; const LL mod = 998244353; int n, p, cnt; int head[MAXN]; int l[MAXN], r[MAXN]; int C[MAXN]; int times; struct edge { int from,to; } G[MAXN]; void add(int u, int v) { G[cnt].to=v; G[cnt].from = head[u]; head[u]=cnt++; } void dfs(int u, int fa)//建立dfs序 { l[u]=++times; for(int i=head[u]; ~i; i=G[i].from) { int v=G[i].to; if(v!=fa) { dfs(v, u); } } r[u]=times; } void init() { cnt=0; times=0; memset(head, -1, sizeof(head)); } int lowbit(int x) { return x&-x; } void add_val(int x, int val) { while(x<=n) { C[x]+=val; x+=lowbit(x); } return ; } int get_sum(int x) { int ans=0; while(x>0) { ans+=C[x]; x-=lowbit(x); } return ans; } int main() { int u, v; scanf("%d %d", &n, &p); init(); for(int i=1; i<=n-1; ++i) { scanf("%d %d", &u, &v); add(u,v); add(v,u); } dfs(p, -1); // for(int i=1; i<=n; ++i) // printf("%d %d %d\n", i, l[i], r[i]); for(int i=1;i<=n;++i) { printf("%d%c", get_sum(r[i])-get_sum(l[i]), " \n"[i==n]); add_val(l[i],1);//这是整个程序最关键的部分,由于是从名次第一开始,所以往后的名次只要在dfs序中有值便是名次比自己高但是是自己的徒弟,如果不在同一子树上,会因为dfs序的r[i]所分开,到最后只是算dfs在(l,r]这个区间的值 } return 0; }