主席树是一种可持久化的线段树
#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 200010;
int cnt = 0;
int a[N], b[N], root[N];
struct
{
int L, R, sum;
} tree[N << 5];
int build(int pl, int pr)
{
int rt = ++cnt;
tree[rt].sum = 0;
int mid = (pl + pr) >> 1;
if (pl < pr)
{
tree[rt].L = build(pl, mid);
tree[rt].R = build(mid + 1, pr);
}
return rt;
}
int update(int pre, int pl, int pr, int x)
{
int rt = ++cnt;
tree[rt].L = tree[pre].L;
tree[rt].R = tree[pre].R;
tree[rt].sum = tree[pre].sum + 1;
int mid = (pl + pr) >> 1;
if (pl < pr)
{
if (x <= mid)
tree[rt].L = update(tree[pre].L, pl, mid, x);
else
tree[rt].R = update(tree[pre].R, mid + 1, pr, x);
}
return rt;
}
int query(int u, int v, int pl, int pr, int k)
{
if (pl == pr)
return pl;
int x = tree[tree[v].L].sum - tree[tree[u].L].sum;
int mid = (pl + pr) >> 1;
if (x >= k)
return query(tree[u].L, tree[v].L, pl, mid, k);
else
return query(tree[u].R, tree[v].R, mid + 1, pr, k - x);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
int size = unique(b + 1, b + 1 + n) - b - 1;
for (int i = 0; i <= n; i++)
{
int x = lower_bound(b + 1, b + 1 + size, a[i]) - b;
root[i] = update(root[i - 1], 1, size, x);
}
while (m--)
{
int x, y, k;
scanf("%d%d%d", &x, &y, &k);
int t = query(root[x - 1], root[y], 1, size, k);
printf("%d\n", b[t]);
}
return 0;
}