//本模板是离散后对权值建树 #include<bits/stdc++.h> #define mid (l+r>>1) using namespace std; const int N=2e5+10; struct TR { int sum,lo,ro; }tr[N<<5]; int tr_cnt;//之后需要初始化=0 int n,m,q,arr[N],brr[N],rt[N];//m是权值的数量 void build(int &o,int l=1,int r=m) { o=++tr_cnt; //tr[o].sum=0; if(l==r)return; build(tr[o].lo,l,mid); build(tr[o].ro,mid+1,r); } void update(int p,int v,int pre,int &o,int l=1,int r=m) { o=++tr_cnt; tr[o]=tr[pre]; tr[o].sum+=v;//都是+1 if(l==r)return; if(p<=mid)update(p,v,tr[pre].lo,tr[o].lo,l,mid); else update(p,v,tr[pre].ro,tr[o].ro,mid+1,r); } //u和v是两个线段树的根,相减后的线段树求第k个的下标位置 int query(int k,int u,int v,int l=1,int r=m) { if(l==r)return l; int tmp=tr[tr[v].lo].sum-tr[tr[u].lo].sum; if(tmp>=k)return query(k,tr[u].lo,tr[v].lo,l,mid); else return query(k-tmp,tr[u].ro,tr[v].ro,mid+1,r); } int main() { int n,q;scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%d",arr+i),brr[i]=arr[i]; sort(brr+1,brr+1+n); m=unique(brr+1,brr+1+n)-brr-1; build(rt[0]); for(int i=1;i<=n;i++) { int p=lower_bound(brr+1,brr+1+m,arr[i])-brr; update(p,1,rt[i-1],rt[i]); } while(q--) { int u,v,k; scanf("%d%d%d",&u,&v,&k); printf("%d ",brr[query(k,rt[u-1],rt[v])]); } return 0; }