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.

108 lines
2.4 KiB

2 years ago
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010, M = 50010;
//快读
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;
}
int n, m;
struct A {
int id, x;
const bool operator<(const A &t) const {
return x < t.x;
}
} a[N];
struct Q {
int id; //第几号查询
int l, r, k; //左右区间第k小
} q[M];
//树状数组
int tr[N];
//查询x的个数和
int query(int x) {
int sum = 0;
for (; x; x -= x & -x) sum += tr[x];
return sum;
}
// x位置上增加c
void update(int x, int c) {
for (; x <= n; x += x & -x) tr[x] += c;
}
//每个询问的答案数组
int ans[M];
//[l,r]:排序后数组上的区间
//[x,y]:询问集合的区间
void solve(int l, int r, int x, int y) {
if (x > y) return; //查询的子区间非法,返回
if (l == r) {
for (int i = x; i <= y; i++) ans[q[i].id] = a[l].x;
return;
}
int mid = (l + r) >> 1;
for (int i = l; i <= mid; i++) update(a[i].id, 1);
int i = x, j = y, t;
while (i <= j) {
while (i <= j && q[i].k <= query(q[i].r) - query(q[i].l - 1)) i++;
while (i <= j && q[j].k > (t = query(q[j].r) - query(q[j].l - 1))) {
q[j].k -= t;
j--;
}
if (i < j)
swap(q[i], q[j]);
}
for (int i = l; i <= mid; i++) update(a[i].id, -1);
solve(l, mid, x, j), solve(mid + 1, r, i, y);
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++) a[i].x = read(), a[i].id = i;
//查询请求
for (int i = 1; i <= m; i++) {
q[i].l = read(), q[i].r = read(), q[i].k = read();
q[i].id = i;
}
sort(a + 1, a + 1 + n); //将原数组的二元组按值大小进行由小到大的排序,同步记录了每个数值对应的序号
//离线处理
//二分区间为[1,n] ,查询区间q[1]~q[m]???
solve(1, n, 1, m);
//输出每次询问的答案
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
return 0;
}