LUOGU P3834 模板可持久化线段树 1(主席树)

Posted sdfzsyq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LUOGU P3834 模板可持久化线段树 1(主席树)相关的知识,希望对你有一定的参考价值。

传送门

解题思路

  主席树模板题,主席树就是一个支持查询历史版本的数据结构,就是在原树的基础上只修改那些受影响的部分以保证时空复杂度。做法就是首先离散化,然后给每个值建一棵线段树,每次建在上一个的基础上,然后查询的时候就变成前缀和相减的形式。时间复杂度(O(nlogn))

代码

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

using namespace std;
const int MAXN = 200005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {f=ch==‘-‘?0:1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
    return f?x:-x;
}

int n,m,a[MAXN],cpy[MAXN],cnt,rt[MAXN];
int ls[MAXN<<5],rs[MAXN<<5],sum[MAXN<<5];

int build(int l,int r){
    int now=++cnt,mid=(l+r)>>1;
    if(l==r) return now;
    ls[now]=build(l,mid);rs[now]=build(mid+1,r);
    return now;
}

int update(int pre,int l,int r,int x){
    int now=++cnt,mid=(l+r)>>1;ls[now]=ls[pre];rs[now]=rs[pre];sum[now]=sum[pre]+1;
    if(l==r) return now;
    if(x<=mid) ls[now]=update(ls[pre],l,mid,x);
    else rs[now]=update(rs[pre],mid+1,r,x);
    return now;
}

int query(int u,int v,int l,int r,int k){
    if(l==r) return l;
    int x=sum[ls[v]]-sum[ls[u]],mid=(l+r)>>1;
    if(x>=k) return query(ls[u],ls[v],l,mid,k);
    else return query(rs[u],rs[v],mid+1,r,k-x);
}

int main(){
    n=rd(),m=rd();int x,y,z;
    for(int i=1;i<=n;i++) a[i]=rd(),cpy[i]=a[i];
    sort(cpy+1,cpy+1+n);int u=unique(cpy+1,cpy+1+n)-cpy-1;
    rt[0]=build(1,n);int tmp;
    for(int i=1;i<=n;i++){
        tmp=lower_bound(cpy+1,cpy+1+u,a[i])-cpy;
        rt[i]=update(rt[i-1],1,u,tmp);
    }
    while(m--){
        x=rd(),y=rd(),z=rd();
        printf("%d
",cpy[query(rt[x-1],rt[y],1,u,z)]);
    }
    return 0;
}

以上是关于LUOGU P3834 模板可持久化线段树 1(主席树)的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3834 模板可持久化线段树 1(主席树)| 静态第k小问题^&

P3834 模板可持久化线段树 1(主席树) 整体二分

解题报告:P3834 模板可持久化线段树 2(主席树)详解

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

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

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