• 【洛谷P3834】(模板)可持久化线段树 1(主席树)


    【模板】可持久化线段树 1(主席树)

    https://www.luogu.org/problemnew/show/P3834

    主席树支持历史查询,空间复杂度为O(nlogn),需要动态开点

    本题用一个类似于前缀和的思想,离散化之后

    用主席树维护每一个前缀的“桶”数组

     

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 #define MAXN 200020
     6 int n,m,a[MAXN],b[MAXN],lc[MAXN<<5],rc[MAXN<<5],root[MAXN<<5],num,sum[MAXN<<5];
     7 inline int read(){
     8     int x=0,f=1; char c=getchar();
     9     while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
    10     while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
    11     return x*f;
    12 }
    13 int build(int l,int r){
    14     int rt=++num;
    15     sum[rt]=0;
    16     int mid=(l+r)>>1;
    17     if(l<r){
    18         lc[rt]=build(l,mid);  //记录左儿子
    19         rc[rt]=build(mid+1,r); //记录右儿子
    20     }
    21     return rt;
    22 }
    23 int update(int last,int l,int r,int p){
    24     int rt=++num;
    25     lc[rt]=lc[last]; rc[rt]=rc[last]; sum[rt]=sum[last]+1;  //新开结点
    26     int mid=(l+r)>>1;
    27     if(l<r){  
    28         if(p<=mid) lc[rt]=update(lc[last],l,mid,p);
    29         else  rc[rt]=update(rc[last],mid+1,r,p);
    30     }
    31     return rt;
    32 }
    33 int query(int u,int v,int l,int r,int k){
    34     if(l>=r) return l;
    35     int t=sum[lc[v]]-sum[lc[u]];          //原序列区间[u,v]中值在[l,r]之间的数的个数
    36     int mid=(l+r)>>1;
    37     if(k<=t) return query(lc[u],lc[v],l,mid,k);
    38     else return query(rc[u],rc[v],mid+1,r,k-t);
    39 }
    40 int main()
    41 {
    42     scanf("%d%d",&n,&m);
    43     for(int i=1;i<=n;i++){
    44         a[i]=read(); b[i]=a[i];
    45     }
    46     sort(b+1,b+1+n);
    47     int h=unique(b+1,b+1+n)-b-1;
    48     root[0]=build(1,h);
    49     for(int i=1;i<=n;i++){
    50         int t=lower_bound(b+1,b+1+h,a[i])-b;
    51         root[i]=update(root[i-1],1,h,t);
    52     }
    53     int x,y,k;
    54     while(m--){
    55         x=read(); y=read(); k=read();
    56         int t=query(root[x-1],root[y],1,h,k);
    57         printf("%d
    ",b[t]);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    Mac 终端自动补全忽略大小写
    AtCoder ABC 155F Perils in Parallel
    AtCoder ABC 155E Payment
    AtCoder ABC 155D Pairs
    AtCoder ABC 154F Many Many Paths
    牛客 边界都是1的最大正方形大小
    牛客 打印N个数组整体最大的Top K
    牛客 数组中子数组的最大累乘积
    牛客 在数组中找到一个局部最小的位置
    牛客 子矩阵最大累加和问题
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9217668.html
Copyright © 2020-2023  润新知