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

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

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>

#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)

using namespace std;
typedef long long ll;//全用ll可能会MLE或者直接WA,试着改成int看会不会A
const ll N=500007;
const ll INF=1e9+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;

template<typename T>void read(T &x)
{
    x=0;char ch=getchar();ll f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x*=f;
}

int n,m,q,cnt;
int a[N],b[N],T[N];
int sum[N<<5],L[N<<5],R[N<<5];

inline void build(int &t,int l,int r)//直接用引用变量&t
{
    int rt=++cnt;//rt是当前节点的编号
    sum[rt]=0;//初始化
    if(l==r)return;
    build(L[rt],l,mid);
    build(R[rt],mid+1,r);
}

inline int update(int p,int l,int r,int x)//p为旧树该位置节点的编号
{
    int rt=++cnt;//新建节点的编号
    L[rt]=L[p];
    R[rt]=R[p];//该节点左右儿子初始化为旧树该位置节点的左右儿子
    sum[rt]=sum[p]+1;//因为插入的a[i](或b[x])在该节点所代表的区间中 所以sum++
    if(l!=r)
    {
        if(x<=mid)L[rt]=update(L[p],l,mid,x);
        //x出现在左子树 因此右子树保持与旧树相同 修改左子树
        else R[rt]=update(R[p],mid+1,r,x);
    }
    return rt;
}

inline int query(int u,int v,int l,int r,int k)
{
    if(l==r)return b[l];
    int num=sum[L[v]]-sum[L[u]];
    if(num>=k)return query(L[u],L[v],l,mid,k);
    else return query(R[u],R[v],mid+1,r,k-num);
}
int sizes;
int main()
{
    read(n),read(m);
    over(i,1,n)
    read(a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    sizes=unique(b+1,b+1+n)-b-1;
    //size为线段树维护的数组的大小==b数组中不重复的数字的个数
    build(T[0],1,sizes); //初始化 建立一颗空树 并把该树的根节点的编号赋值给T[0]
    over(i,1,n)
    {
        int t=lower_bound(b+1,b+1+sizes,a[i])-b;
        T[i]=update(T[i-1],1,sizes,t);
    }
    //cout<<"123"<<endl;
    while(m--)
    {
        int l,r,k;
        read(l),read(r),read(k);
        printf("%d\n",query(T[l-1],T[r],1,sizes,k));
    }
    return 0;
}