https://www.zybuluo.com/ysner/note/1282069

题面

给一颗带点权的树,求每个点的子树中比该点权值大的点的个数。

  • \(n\leq10^5\)

解析

首先有个很无脑的方法。

用一个权值树状数组维护所有点权(离散化后的)。

每到一个点,询问比该点大的数的个数,然后把这个点权加入树状数组。

dfs回溯以后,再次询问,用这次答案减去上次答案。

这样可以在每个点上直接询问答案。

复杂度\(O(nlog^2n)\)。常数巨小。

然而我做这道题是想入门线段树合并。

其实思想正好相反。

我们不删点权,只把信息从下面合并上来。

对每个点,把它儿子的值域线段树与自己合并。

具体来说是从根节点出发,统计根结点的值,然后合并左儿子右儿子。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  11. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  12. using namespace std;
  13. const int N=5e5+100,M=1e7;
  14. struct Edge{int to,nxt;}e[N<<1];
  15. int a[N],w[N],n,h[N],cnt,tot,ans[N],rt[M],s[M],ls[M],rs[M],tim;
  16. il void add(re int u,re int v){e[++cnt]=(Edge){v,h[u]};h[u]=cnt;}
  17. il ll gi()
  18. {
  19. re ll x=0,t=1;
  20. re char ch=getchar();
  21. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  22. if(ch=='-') t=-1,ch=getchar();
  23. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  24. return x*t;
  25. }
  26. il void Modify(re int &x,re int l,re int r,re int W)
  27. {
  28. if(!x) x=++tim;
  29. ++s[x];
  30. if(l==r) return;
  31. re int mid=l+r>>1;
  32. if(W<=mid) return Modify(ls[x],l,mid,W);
  33. return Modify(rs[x],mid+1,r,W);
  34. }
  35. il int Query(re int x,re int l,re int r,re int W)
  36. {
  37. if(!x) return 0;
  38. if(l>=W) return s[x];
  39. re int mid=l+r>>1;
  40. if(W<=mid) return Query(ls[x],l,mid,W)+Query(rs[x],mid+1,r,W);
  41. return Query(rs[x],mid+1,r,W);
  42. }
  43. il int Merge(re int u,re int v)
  44. {
  45. if(!u) return v;if(!v) return u;
  46. re int p=++tim;
  47. s[p]=s[u]+s[v];
  48. ls[p]=Merge(ls[u],ls[v]);
  49. rs[p]=Merge(rs[u],rs[v]);
  50. return p;
  51. }
  52. il void dfs(re int u)
  53. {
  54. for(re int i=h[u];i+1;i=e[i].nxt)
  55. {
  56. re int v=e[i].to;
  57. dfs(v);
  58. rt[u]=Merge(rt[u],rt[v]);
  59. }
  60. ans[u]=Query(rt[u],1,tot,w[u]+1);
  61. Modify(rt[u],1,tot,w[u]);
  62. }
  63. int main()
  64. {
  65. memset(h,-1,sizeof(h));
  66. n=gi();
  67. fp(i,1,n) a[i]=w[i]=gi();
  68. fp(v,2,n)
  69. {
  70. re int u=gi();
  71. add(u,v);
  72. }
  73. sort(a+1,a+1+n);
  74. tot=unique(a+1,a+1+n)-a-1;
  75. fp(i,1,n) w[i]=lower_bound(a+1,a+1+tot,w[i])-a;
  76. dfs(1);
  77. fp(i,1,n) printf("%d\n",ans[i]);
  78. return 0;
  79. }

luogu3605晋升者计数的更多相关文章

  1. Luogu3605 [USACO17JAN]Promotion Counting晋升者计数

    Luogu3605 [USACO17JAN]Promotion Counting晋升者计数 给一棵 \(n\) 个点的树,点 \(i\) 有一个权值 \(a_i\) .对于每个 \(i\) ,求 \( ...

  2. 线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数

    题面:P3605 [USACO17JAN]Promotion Counting晋升者计数 题解:这是一道万能题,树状数组 || 主席树 || 线段树合并 || 莫队套分块 || 线段树 都可以写..记 ...

  3. 树状数组 P3605 [USACO17JAN]Promotion Counting晋升者计数

    P3605 [USACO17JAN]Promotion Counting晋升者计数 题目描述 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者! 为了方便,把奶牛从 ...

  4. 【题解】晋升者计数 Promotion Counting [USACO 17 JAN] [P3605]

    [题解]晋升者计数 Promotion Counting [USACO 17 JAN] [P3605] 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训.!牛是可怕的管理者! [题目描 ...

  5. [USACO17JAN] 晋升者计数 dfs序+树状数组

    [USACO17JAN] 晋升者计数 dfs序+树状数组 题面 洛谷P3605 题意:一棵有点权的树,找出树中所有\((u,v)\)的对数,其中\(u,v\)满足\(val(u)\le val(v)\ ...

  6. [USACO17JAN]Promotion Counting晋升者计数

    题目描述 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者! 为了方便,把奶牛从 1 \cdots N(1 \leq N \leq 100, 000)1⋯N(1≤N ...

  7. 【USACO17JAN】Promotion Counting晋升者计数 线段树+离散化

    题目描述 The cows have once again tried to form a startup company, failing to remember from past experie ...

  8. 洛谷P3605 [USACO17JAN] Promotion Counting 晋升者计数 [线段树合并]

    题目传送门 Promotion Counting 题目描述 The cows have once again tried to form a startup company, failing to r ...

  9. 洛谷 P3605 [USACO17JAN]Promotion Counting晋升者计数

    题目描述 The cows have once again tried to form a startup company, failing to remember from past experie ...

随机推荐

  1. cookie和session的区别及session的生命周期

    这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录 ...

  2. 基于Vue的简单日历组件

    日历组件 由于移动端项目中需要用到日历组件,网上找了下,没看到几个合适的,就尝试着自己写一个.然后发现也不是很复杂,目前只做了最基本的功能,大家也可以拿去做做二次开发. 如何写一个日历组件 基础效果如 ...

  3. c++基础_回文数

    #include <iostream> using namespace std; int main(){ ;i<;i++){ ; int n=i;//暂存该四位数来计算 ,以防改变i ...

  4. 洛谷 1197 [JSOI2008]星球大战

    [题解] 把询问离线,倒着加点,并查集维护连通性即可. #include<cstdio> #include<cstring> #include<algorithm> ...

  5. Qt笔记——2.编写多窗口程序

    所学教程网址:http://www.qter.org/portal.php?mod=view&aid=27&page=2 设置按钮文字 MainWindow::MainWindow(Q ...

  6. Python安装配置

    Python下载 官网下载地址:https://www.python.org/downloads/windows/ 下载安装包: python-3.5.0-amd64(64位).exe python- ...

  7. xtu Shortest Path

    Acceteped : 23   Submit : 61 Time Limit : 5000 MS   Memory Limit : 65536 KB Description 题目描述 N(3≤N≤1 ...

  8. JavaEE JDBC 怎么加载驱动

    JDBC怎么加载驱动 @author ixenos 分析 1.JDBC是一套连接数据库的接口(放在java.util.sql.Driver类中),不同的数据库依此接口各自实现Java连接到数据库的操作 ...

  9. UVA 10652 凸包问题

    #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> # ...

  10. Android定位(是否使用GPS进行定位)

    TencentLocationRequest request = TencentLocationRequest.create(); request.setRequestLevel(TencentLoc ...