#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn= 100010;
//segl segr 存線段樹左右點 , chl chr 存主席樹的左右子樹的k值(即序號下標),s爲區間和
struct node{
int segl, segr, chl ,chr, s;
}tree[30*maxn];
// root 存儲每一個單鏈起始的位置(k值)
int root[maxn*2], tot, n, m, na[maxn*2], nb[maxn*2], len;
int binary(int x){ //二分離散
int lef= 1, rig= len, mid;
while( lef <= rig){
mid = (lef + rig)>> 1;
if( na[mid] < x) lef = mid + 1;
else if( na[mid] > x) rig = mid - 1;
else return mid;
}
}
int maketree(int lef, int rig){
if( lef > rig) return 0;
int k, mid;
k = ++tot;
tree[k].segl = lef;
tree[k].segr = rig;
tree[k].s = 0;
mid = (lef + rig) >> 1;
if( lef == rig) return k;
tree[k].chl = maketree(lef, mid);
tree[k].chr = maketree(mid+1, rig);
return k;
}
//對於每一個x,都可理解爲形成一棵新樹,通過下標鏈過去
int change(int p, int x, int v){
int k;
k = ++tot;
tree[k].segl = tree[p].segl;
tree[k].segr = tree[p].segr;
tree[k].chl = tree[p].chl;
tree[k].chr = tree[p].chr;
tree[k].s = tree[p].s + v;
if( tree[p].segl ==x && x == tree[p].segr) return k;
int mid = ( tree[p].segl + tree[p].segr) >> 1;
if( x <= mid) tree[k].chl = change(tree[p].chl, x, v);
else tree[k].chr = change(tree[p].chr, x, v);
return k;
}
int quary(int y, int x, int k){
//cout<<y<<" "<<x<<" "<<k<<endl;
if( tree[y].segl == tree[y].segr ) return tree[y].segl;
int t = tree[tree[y].chl].s - tree[tree[x].chl].s;
if( k<= t)return quary(tree[y].chl, tree[x].chl, k);
else return quary(tree[y].chr, tree[x].chr, k - t);
}
int main(){
//freopen("1.txt", "r", stdin);
int i, aa, bb, cc;
while( scanf("%d%d", &n, &m) != EOF){
for( i= 1; i<= n; i++){
scanf("%d", &na[i]);
nb[i] = na[i];
}
sort(na+1, na+ n+1);
len = unique(na+1, na+(n+1)) - (na+1);
for( i= 1; i<=n; i++)
nb[i] = binary(nb[i]);
tot = 0;
root[0] = maketree(1, len);
for( i= 1; i<=n; i++){
root[i] = change(root[i-1], nb[i], 1);
// cout<<i<<" "<<root[i]<<endl;
}
for( i= 0; i<m; i++){
scanf("%d%d%d", &aa, &bb, &cc);
printf("%d\n", na[quary(root[bb], root[aa-1], cc)]);
}
}
return 0;
}