青出于蓝胜于蓝 dfs+树状数组

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

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

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

输入格式

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

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

输出格式

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

行末不要输出多余的空格。

样例输入

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

挺好的一个题,就记录下了。

算出每个点有多少个儿子节点,然后求相应的区间与l逆序对的数量。

 1 #include <bits/stdc++.h>
 2 #define lowbit(x) (-x&(x))
 3 using namespace std;
 4 const int N = 1e5+10;
 5 vector<int> vs[N];
 6 typedef pair<int,int> P;
 7 vector<P> vs1[N];
 8 int a[N], d[N], sum[N], dp[N][2], res;
 9 
10 int dfs(int v, int f) {
11     a[++res] = v;
12     int sum = 0;
13     for(auto u : vs[v]) {
14         if(u == f) continue;
15         d[u] = dfs(u, v);
16         sum += d[u]+1;
17     }
18     return sum;
19 }
20 void add(int x, int y) {
21     while(x < N) {
22         sum[x] += y;
23         x += lowbit(x);
24     }
25 }
26 int query(int x) {
27     int s = 0;
28     while(x > 0) {
29         s += sum[x];
30         x -= lowbit(x);
31     }
32     return s;
33 }
34 int main() {
35     int n, p, u, v;
36     scanf("%d%d", &n, &p);
37     for(int i = 1; i < n; i ++) {
38         scanf("%d%d", &u, &v);
39         vs[u].push_back(v);
40         vs[v].push_back(u);
41     }
42     d[p] = dfs(p, -1);
43     // for(int i = 1; i <= n; i ++) printf("%d ",a[i]);printf("\n");
44     // for(int i = 1; i <= n; i ++) printf("%d ",d[a[i]]);printf("\n");
45     for(int i = 1; i <= n; i ++) {
46         vs1[i+d[a[i]]].push_back(P(a[i],i));
47     }
48     for(int i = n; i >= 1; i --) {
49         for(auto p : vs1[i]) {
50             dp[p.first][0] = query(p.first);
51         }
52         dp[a[i]][1] = query(a[i]);
53         // printf("%d\n",i);
54         add(a[i], 1);
55     }
56     for(int i = 1; i <= n; i ++) printf("%d%c",dp[i][1]-dp[i][0]," \n"[i==n]);
57     return 0;
58 }

 

posted @ 2018-10-25 20:48  starry_sky  阅读(253)  评论(0编辑  收藏  举报