- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define maxn 100005
- #define maxd 21
- struct seg{
- int l,r,m;
- }tr[maxn<<2];
- int s[maxn],segt[maxd][maxn<<2],n;
- void build(int l,int r,int rt,int d){
- tr[rt].l=l;
- tr[rt].r=r;
- tr[rt].m=(l+r)>>1;
- int m=tr[rt].m;
- if(l==r){
- segt[d][l]=s[l];
- return ;
- }
- build(l,m,rt<<1,d+1);
- build(m+1,r,rt<<1|1,d+1);
- int i=l,j=m+1,k=l;
- while(i<=m && j<=r){//数值的归并
- if(segt[d+1][i]>segt[d+1][j])
- segt[d][k++]=segt[d+1][j++];
- else
- segt[d][k++]=segt[d+1][i++];
- }
- while(i<=m)
- segt[d][k++]=segt[d+1][i++];
- while(j<=r)
- segt[d][k++]=segt[d+1][j++];
- }
- int countsig(int l,int r,int rt,int key,int d){//找出区间比其小的个数
- return lower_bound(segt[d]+l,segt[d]+r+1,key)-(segt[d]+l);
- }
- int count(int l,int r,int rt,int key,int d){
- if(tr[rt].l == l && tr[rt].r == r){
- return countsig(l,r,rt,key,d);
- }
- int m=tr[rt].m;
- if(r<=m)
- return count(l,r,rt<<1,key,d+1);
- else if(l>m)
- return count(l,r,rt<<1|1,key,d+1);
- else
- return count(l,m,rt<<1,key,d+1)+count(m+1,r,rt<<1|1,key,d+1);
- }
- int query(int L,int R,int cnt){
- int l=1,r=n;
- while(l<=r){
- int m=(l+r)>>1;
- int t=count(L,R,1,segt[1][m],1);
- if(t>=cnt)
- r=m-1;
- else
- l=m+1;
- }
- return segt[1][l-1];
- }
- int main(){
- int m;
- while(~scanf("%d %d",&n,&m)){
- for(int i=1;i<=n;i++)
- scanf("%d",&s[i]);
- build(1,n,1,1);
- while(m--){
- int l,r,cnt;
- scanf("%d %d %d",&l,&r,&cnt);
- printf("%d\n",query(l,r,cnt));
- }
- }
- return 0;
- }