zoukankan      html  css  js  c++  java
  • [线段树合并] Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数

    给一棵 N 个点的树,每个点有一个权值,求每个点的子树中有多少个点的权值比它大。

    考虑线段树合并,将权值离散化,每个点开一棵权值线段树。

    求答案时直接在权值线段树上查询,线段树合并时类似于可并堆。

    要注意的是线段树要动态开点,合并时别忘了 up。

    内存什么的最好算一下,数组别开小了。

     1 #include<bits/stdc++.h>
     2 #define rep(i,a,b) for(register int i=a;i<=b;++i)
     3 #define rpd(i,a,b) for(register int i=a;i>=b;--i)
     4 #define rep1(i,x) for(register int i=head[x];i;i=nxt[i])
     5 typedef long long ll;
     6 const int N=2e5+5;
     7 using namespace std;
     8 inline int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    11     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 struct Tree{int x,l,r;}t[N<<4];
    15 int n,tot,cnt;int a[N],b[N],head[N],nxt[N],to[N],rt[N],ans[N];
    16 void add(int u,int v){nxt[++tot]=head[u];head[u]=tot;to[tot]=v;}
    17 void up(int k){t[k].x=t[t[k].l].x+t[t[k].r].x;}
    18 void build(int &k,int l,int r,int x){
    19     k=++cnt;if(l==r){t[k].x=1;return;}
    20     int mid=l+r>>1;
    21     if(mid>=x)build(t[k].l,l,mid,x);
    22     else build(t[k].r,mid+1,r,x);
    23     up(k);
    24 }
    25 int find(int k,int l,int r,int L,int R){
    26     if(L<=l&&r<=R)return t[k].x;
    27     if(l>R||r<L)return 0;
    28     int mid=l+r>>1;
    29     return find(t[k].l,l,mid,L,R)+find(t[k].r,mid+1,r,L,R);
    30 }
    31 int merge(int x,int y){
    32     if(!x||!y)return x+y;
    33     t[x].x+=t[y].x;
    34     t[x].l=merge(t[x].l,t[y].l);
    35     t[x].r=merge(t[x].r,t[y].r);
    36     up(x);
    37     return x;
    38 }
    39 void dfs(int x){
    40     rep1(i,x){
    41         int p=to[i];dfs(p);
    42         rt[x]=merge(rt[x],rt[p]);
    43     }
    44     int k=lower_bound(b+1,b+n+1,a[x])-b;
    45     ans[x]=find(rt[x],1,n,k+1,n);
    46 }
    47 int main(){
    48     n=read();rep(i,1,n)b[i]=a[i]=read();
    49     sort(b+1,b+n+1);
    50     rep(i,1,n){
    51         int k=lower_bound(b+1,b+n+1,a[i])-b;
    52         build(rt[i],1,n,k);
    53     }
    54     rep(i,2,n)add(read(),i);dfs(1);
    55     rep(i,1,n)printf("%d
    ",ans[i]);
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    ORACLE 数据迁移到SQL SEVER2005的问题
    sql server性能分析检测数据库阻塞语句
    经典存储过程
    sql server性能分析查询死锁的sql语句
    sql server性能分析索引使用效率评估
    discuz!X2.5不改代码即可去掉网址后面的forum.php后缀
    discuz!X2.5伪静态设置
    详解ListView
    frameset、frame和iframe的区别
    android中的Context到底该怎么用
  • 原文地址:https://www.cnblogs.com/maximumhanyu/p/11433029.html
Copyright © 2011-2022 走看看