洛谷 p3834 主席树

题目链接:https://www.luogu.org/problem/P3834

主席树求静态区间第k小

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 200005
#define ll long long
int T[maxn*20],L[maxn*20],R[maxn*20],sum[maxn*20],tot;
ll a[maxn],b[maxn];
inline int update(int pre,int l,int r,int x)
{
    int rt=++tot;
    L[rt]=L[pre];
    R[rt]=R[pre];
    sum[rt]=sum[pre]+1;
    if(l<r)
    {
        int mid=l+r>>1;
        if(x<=mid)L[rt]=update(L[pre],l,mid,x);
        else R[rt]=update(R[pre],mid+1,r,x);
    }
    return rt;
}
inline int query(int u,int v,int l,int r,int k)
{
    if(l>=r)return l;
    int x=sum[L[v]]-sum[L[u]],mid=l+r>>1;
    if(x>=k)return query(L[u],L[v],l,mid,k);
    else return query(R[u],R[v],mid+1,r,k-x);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    int len=unique(b+1,b+1+n)-b-1;
    tot=0;
    for(int i=1;i<=n;i++)
    {
        int pos=lower_bound(b+1,b+1+len,a[i])-b;
        T[i]=update(T[i-1],1,len,pos);
    }
    int l,r,k;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&l,&r,&k);
        printf("%lld\n",b[query(T[l-1],T[r],1,len,k)]);
    }
    return 0;
}

 

posted on 2019-08-03 10:44  che027  阅读(99)  评论(0编辑  收藏  举报

导航