青出于蓝胜于蓝 dfs+树状数组
Posted xingkongyihao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了青出于蓝胜于蓝 dfs+树状数组相关的知识,希望对你有一定的参考价值。
武当派一共有 nn 人,门派内 nn 人按照武功高低进行排名,武功最高的人排名第 11,次高的人排名第 22,... 武功最低的人排名第 nn。现在我们用武功的排名来给每个人标号,除了祖师爷,每个人都有一个师父,每个人可能有多个徒弟。
我们知道,武当派人才辈出,连祖师爷的武功都只能排行到 pp。也就是说徒弟的武功是可能超过师父的,所谓的青出于蓝胜于蓝。
请你帮忙计算每个人的所有子弟(包括徒弟的徒弟,徒弟的徒弟的徒弟....)中,有多少人的武功超过了他自己。
输入格式
输入第一行两个整数 n, p(1 le n le 100000, 1 le p le n)。
接下来 n-1n−1 行,每行输入两个整数 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(" "); 44 // for(int i = 1; i <= n; i ++) printf("%d ",d[a[i]]);printf(" "); 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 ",i); 54 add(a[i], 1); 55 } 56 for(int i = 1; i <= n; i ++) printf("%d%c",dp[i][1]-dp[i][0]," "[i==n]); 57 return 0; 58 }
以上是关于青出于蓝胜于蓝 dfs+树状数组的主要内容,如果未能解决你的问题,请参考以下文章