计蒜客♂计蒜客♂计蒜客♂计蒜客

[模板]可持久化线段树

2019-02-23 15:40:26


可持久化线段树-主席树

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int n,q;
namespace ZXTree{
    int totID = 0;
    int L[maxn << 5],R[maxn << 5],sumv[maxn << 5];
    int build(int l,int r){
        int id = ++totID;
        int mid = l + r >> 1;
        if(l != r){
            L[id] = build(l,mid);
            R[id] = build(mid+1,r);
        }
        return id;
    }
    int update(int preID,int l,int r,int x,int v){
        int id = ++totID;
        int mid = l + r >> 1;
        L[id] = L[preID],R[id] = R[preID],sumv[id] = sumv[preID] + v;
        if(l != r){
            if(x <= mid) L[id] = update(L[id],l,mid,x,v);
            else R[id] = update(R[id],mid+1,r,x,v);
        }
        return id;
    }
    int query(int u,int v,int l,int r,int k){
        if(l == r) return l;
        int mid = l + r >> 1;
        int lcnt = sumv[L[v]] - sumv[L[u]];
        if(lcnt >= k) return query(L[u],L[v],l,mid,k);
        else return query(R[u],R[v],mid+1,r,k-lcnt);
    }
}
int a[maxn],b[maxn],c[maxn];
int T[maxn];
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) {
        scanf("%d",a+i);
        b[i] = a[i];
    }
    sort(a+1,a+1+n);
    int m = unique(a+1,a+1+n) - a - 1;
    T[0] = ZXTree::build(1,m);
    for(int i=1;i<=n;i++) {
        c[i] = lower_bound(a+1,a+1+m,b[i]) - a;
        T[i] = ZXTree::update(T[i-1],1,m,c[i],1);
    }
    while(q--){
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",a[ZXTree::query(T[l-1],T[r],1,m,k)]);
    }
    return 0;
}