You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
//快读
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
const int N = 2e5 + 10;
int n, m;
int a[N];
vector<int> ys;
struct Node {
int l, r, cnt;
} tr[N << 5];
int root[N], idx;
int find(int x) {
return lower_bound(ys.begin(), ys.end(), x) - ys.begin();
}
//经典的主席树插入
void insert(int &u, int l, int r, int x) {
tr[++idx] = tr[u]; //新开一个节点idx++,将新节点指向旧的tr[u]
u = idx; //因为是引用为了回传正确值需要u=idx-1
tr[u].cnt++; //新节点的cnt因为多插入了一个数字所以个数+1,这样处理的话省去了pushup
if (l == r) return; //如果已经到了叶子节点,上面的操作就足够了,可以直接返回,否则需要继续向下递归
int mid = (l + r) >> 1;
if (x <= mid)
insert(tr[u].l, l, mid, x); //因为tr[u]进入本函数时最先把旧的复制过来所以tr[u].l也是上一个版本的左儿子节点
else
insert(tr[u].r, mid + 1, r, x);
}
int query(int p, int q, int l, int r, int k) {
if (l == r) return l;
int mid = (l + r) >> 1;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
if (k <= cnt)
return query(tr[p].l, tr[q].l, l, mid, k);
else
return query(tr[p].r, tr[q].r, mid + 1, r, k - cnt);
}
int main() {
//文件输入输出
#ifndef ONLINE_JUDGE
freopen("P3834.in", "r", stdin);
#endif
n = read(), m = read();
for (int i = 1; i <= n; i++) {
a[i] = read();
ys.push_back(a[i]);
}
//数据范围太大直接建线段树会MLE但是比较稀疏可以离散化后用相对应的序号数据量就小了
sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
// 0号版本没有内容时主席树是不需要进行build的,强行build时可能会有部分测试点TLE
// 0号版本有内容时主席树是需要build的不build初始值无法给上
//主席树的数字增加每增加一个就相当于增加了一个版本root[i]记录了版本i的根节点
for (int i = 1; i <= n; i++) {
root[i] = root[i - 1];
insert(root[i], 0, ys.size() - 1, find(a[i]));
}
while (m--) {
int l, r, k;
l = read(), r = read(), k = read();
printf("%d\n", ys[query(root[l - 1], root[r], 0, ys.size() - 1, k)]);
}
return 0;
}