#include <iostream>
using namespace std;
const long MAXN = 100010;
long arr[20][MAXN];
long ori[MAXN];
long n, m;
bool flag;
inline long MIN(long a, long b)
{
return a < b ? a : b;
}
inline long MAX(long a, long b)
{
return a > b ? a : b;
}
void merge_tree(long root, long a, long b, long depth)
{
if (a == b)
{
arr[depth][a] = ori[a];
return;
}
else
{
long mid = (a + b) / 2;
merge_tree(root<<1, a, mid, depth+1);
merge_tree((root<<1)+1, mid+1, b, depth+1);
long i, j, k;
for (i=a, j=mid+1, k=a; i<=mid&&j<=b;)
{
if (arr[depth+1][i] < arr[depth+1][j])
{
arr[depth][k++] = arr[depth+1][i++];
}
else
{
arr[depth][k++] = arr[depth+1][j++];
}
}
while (i <= mid)
{
arr[depth][k++] = arr[depth+1][i++];
}
while (j <= b)
{
arr[depth][k++] = arr[depth+1][j++];
}
}
}
long query(long root, long a, long b, long l, long r, long depth, long num)
{
if (a == l && b == r)
{
long low = a, high = b, mid;
while (low <= high)
{
mid = (low + high) / 2;
if (arr[depth][mid] < num)
{
low = mid + 1;
}
else if (arr[depth][mid] > num)
{
high = mid - 1;
}
else
{
flag = true;
return mid-a+1;
}
}
return high-a+1;
}
else
{
long ans = 0, mid = (a+b)/2;
if (l <= mid)
{
ans += query(root<<1, a, mid, l, MIN(r,mid), depth+1, num);
}
if (r > mid)
{
ans += query((root<<1)+1, mid+1, b, MAX(l, mid+1), r, depth+1, num);
}
return ans;
}
}
int main()
{
while (scanf("%ld %ld", &n, &m) != EOF)
{
long i;
for (i = 1; i <= n; ++i)
{
scanf("%ld", &ori[i]);
}
merge_tree(1, 1, n, 0);
for (i = 1; i <= m; ++i)
{
long k, l, r;
scanf("%ld %ld %ld", &l, &r, &k);
long low=-1000000000, high=1000000000, mid;
while (low <= high)
{
mid = (low+high)/2;
flag = false;
long res = query(1, 1, n, l, r, 0, mid);
if (res == k && flag)
{
printf("%ld\n", mid);
break;
}
else if (res < k)
{
low = mid + 1;
}
else if (res > k || (res == k && !flag))
{
high = mid - 1;
}
}
}
}
return 0;
}