应该是主席树的最普通最简单的应用,没有修改操作,查询静态区间第k小;
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn=2e5+7;
int root[maxn],idx,cnt=1,g[maxn],li[maxn];
int n,m;
struct node{
int l,r,sie;
}tree[maxn<<5];
int find(int x){
int l=0,r=cnt;
while(l<r){
int mid=l+r>>1;
if(li[mid]>=x)r=mid;
else l=mid+1;
}
return l;
}
int build(int l,int r){
int now=++idx;
if(l<r){
int mid=l+r>>1;
tree[now].l=build(l,mid);
tree[now].r=build(mid+1,r);
}
return now;
}
int update(int pre,int x,int l,int r){
int now=++idx,mid=l+r>>1;
tree[now]=tree[pre];tree[now].sie++;
if(l<r){
if(x<=mid)tree[now].l=update(tree[pre].l,x,l,mid);
else tree[now].r=update(tree[pre].r,x,mid+1,r);
}
return now;
}
int query(int L,int R,int l,int r,int k){
if(l==r)return l;
int temp=tree[tree[R].l].sie-tree[tree[L].l].sie,mid=l+r>>1;
if(k<=temp)return query(tree[L].l,tree[R].l,l,mid,k);
return query(tree[L].r,tree[R].r,mid+1,r,k-temp);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&g[i]),li[i]=g[i];
sort(li+1,li+1+n);
for(int i=2;i<=n;i++)if(li[i]!=li[cnt])li[++cnt]=li[i];
root[0]=build(1,cnt);
for(int i=1;i<=n;i++)root[i]=update(root[i-1],find(g[i]),1,cnt);
int a,b,c;
while(m--){
scanf("%d%d%d",&a,&b,&c);printf("%d\n",li[query(root[a-1],root[b],1,cnt,c)]);
}
return 0;
}