#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 100000
int tree[20][MAX+50]; //第一维存原值,后来的存划分后的左右子树的值
int toLeft[20][MAX+50]; //代表当前层区间[left,right]进入左子树的数目
int sorted[MAX+50]; //排序好的数组
/**
* 建树函数
* level: 当前层数
* left: 当前层第一个元素的下标
* right: 当前层最后一个元素的下标
*/
void build_tree(int level,int left,int right) {
if(left==right) return ;//当区间内只有一个元素时无须再划分
int mid=(left+right)>>1;//[left,mid]是下一层的左子树, [mid+1,right]是下一层的右子树,mid是左子树的最后一个元素的下标
int suppose=mid-left+1;//suppose是该层中位数被分配到左子树的个数,这里猜测它是一个最大可能的数,mid-left+1就是左子树的元素个数
for(int i=left; i<=right; i++)
if(tree[level][i]<sorted[mid])//suppose要减去该层所有元素里小于中位数的个数 ,因为小于中位数的数一定会分到左子树,而他们不是中位数,所以中位数分配到左子树的个数会减去这些数的个数,这样就得到了正确的suppose值
suppose--;
int subLeft=left,subRight=mid+1;//subLeft是左子树的第一个元素的下标, subRight是右子树的第一个元素的下标
for(int i=left; i<=right; i++) {//对当前层每个元素进行划分,根据划分算法分到左子树或右子树
if(i==left)
toLeft[level][i]=0;//如果是第一个元素,那么设[left,i]区间内分配到左子树的元素数量为0
else
toLeft[level][i]=toLeft[level][i-1];//如果不是第一个元素,那么设[left,i]区间内分配到左子树的元素数量为[left,i-1]区间内分配到左子树的元素数量
if(tree[level][i]<sorted[mid] || tree[level][i]==sorted[mid]&&suppose>0) {//如果元素小于中位数,或者元素等于中位数并且剩余分配到左子树的中位数的名额>0,就把元素分配到左子树
tree[level+1][subLeft++]=tree[level][i];//将元素分配到左子树
toLeft[level][i]++;//[left,i]区间内分配到左子树的元素数量+1
if(tree[level][i]==sorted[mid])//如果分配到左子树的元素是中位数,那么剩余分配到左子树的中位数的名额-1
suppose--;
} else
tree[level+1][subRight++]=tree[level][i];//将元素分配到右子树
}
build_tree(level+1,left,mid);//划分左子树
build_tree(level+1,mid+1,right);//划分右子树
}
/**
* 查询函数
* level: 当前层数
* left: 当前层第一个元素的下标
* right: 当前层最后一个元素的下标
* qleft: 查询区间中第一个元素的下标
* qright: 查询区间中最后一个元素的下标
* k: 查询结果是查询区间中第k大的值
*/
int query(int level,int left,int right,int qleft,int qright,int k) {
if(qleft==qright)
return tree[level][qleft];//查询区间中只有一个元素,那么就返回这个元素
int mid=(left+right)>>1;//[left,mid]是下一层的左子树, [mid+1,right]是下一层的右子树,mid是左子树的最后一个元素的下标
int lef; //lef是区间[left,qleft-1]中进入左子树的个数(就是当前层中查询区间左边的元素进入左子树的个数)
int tolef; //tolef是区间[qleft,qright]中进入左子树的个数(就是当前层中查询区间内的元素进入左子树的个数)
if(qleft==left)
lef=0,tolef=toLeft[level][qright];//如果查询区间的第一个元素下标=当前层第一个元素的下标,那么当前层中查询区间左边没有元素,所以lef=0
else
lef=toLeft[level][qleft-1],tolef=toLeft[level][qright]-lef;//利用前缀和思想计算tolef:toLeft[level][qright](查询区间左边+查询区间内)-lef(查询区间左边)=tolef(查询区间内)
if(k<=tolef) {//我们要的是查询区间内第k大的数,如果k<=tolef,即查询区间内的元素进入左子树的个数>=k,那么我们的答案一定在左子树中
int newleft=left+lef;//左子树第一个元素的下标+查询区间左边的元素进入左子树的个数=当前层查询区间的第一个元素的下标在左子树中对应的下标
int newright=newleft+tolef-1; //当前层查询区间的第一个元素的下标在左子树中对应的下标+当前层中查询区间内的元素进入左子树的个数-1=当前层查询区间的最后一个元素的下标在左子树中对应的下标
return query(level+1,left,mid,newleft,newright,k);//在左子树中查询
} else {
int newleft=mid+qleft-left-lef+1;
//qleft-left为当前层中查询区间左边的元素数量
//qleft-left-lef为当前层中查询区间左边区间里存到右子树的元素的个数(总元素个数-存进左子树的个数)
//(mid+1)+(qleft-left-lef)为当前层查询区间的第一个元素的下标在右子树中对应的下标(右子树第一个元素的下标+当前层中查询区间左边区间里存到右子树的元素的个数)
int newright=newleft+qright-qleft+1-tolef-1;
//qright-qleft+1为当前层中查询区间内的元素数量
//qright-qleft+1-tolef为为当前层中查询区间里存到右子树的元素的个数(总元素个数-存进左子树的个数)
//newleft+(qright-qleft+1-tolef)-1为当前层查询区间的最后一个元素的下标在右子树中对应的下标(当前层查询区间的第一个元素的下标在右子树中对应的下标+当前层中查询区间里存到右子树的元素的个数-1)
return query(level+1,mid+1,right,newleft,newright,k-tolef);//在右子树中查询
}
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%d",&tree[0][i]);
sorted[i]=tree[0][i];
}
sort(sorted+1,sorted+n+1);//排序以便在建树时 多次获得不同区间的中位数
build_tree(0,1,n);//建树,当前层数0,第一个元素下标为1,最后一个元素下标为n
for(int i=0; i<m; i++) {
int l,r,k;//输入l,r,k,指求出在下标l~r区间内第k大的数,[l,r]是查询区间
scanf("%d%d%d",&l,&r,&k);
int ans=query(0,1,n,l,r,k);//在第0层[1,n]区间内(就是题目给出的整个数组范围)查询区间[l,r]中第k大的数
printf("%d\n",ans);
}
return 0;
}