108 lines
2.4 KiB
C++
108 lines
2.4 KiB
C++
#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;
|
||
} |