关键:
1.离线操作:
将询问区间从左到右排序,然后依次插入区间内的值,在处理下一个询问时,删去上个询问插入的但当前询问不需要插入的数。
m次询问总体复杂度为 2nlog(n).
2.本题注意要离散化
3.二分(手写upper_bound)来查询第k小的数
#include
#include
#include
using namespace std;
#define maxn 100005
int a[maxn], b[maxn], c[maxn], p[maxn];
int n, m;
struct Q {
int l, r, k, id, ans;
} q[maxn >> 1];
int cmp1(Q a, Q b) {
return a.l < b.l || (a.l == b.l && a.r < b.r);
}
int cmp2(Q a, Q b) {
return a.id < b.id;
}
void add(int x, int v) {
for( ; x <= n ; x += x&-x)
c[x] += v;
}
int sum(int x) {
int s = 0;
for( ;x > 0; x -= x&-x)
s += c[x];
return s;
}
int bin(int key) // upper_bound
{
int l = 1, r = n;
while(l <= r) {
int mid = (l + r) >> 1;
if(sum(mid) < key)
l = mid + 1;
else
r = mid - 1;
}
return l;
}
int main() {
int i, j;
while(~scanf("%d%d", &n, &m)) {
for(i = 1; i <= n; i++)
scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + n + 1);
int len = unique(b + 1, b + n + 1) - b - 1;
memset(c, 0, sizeof(c));
for(i = 0; i < m; i++)
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k), q[i].id = i;
sort(q, q + m, cmp1);
for(i = 0; i < m; i++) {
int l, r;
if(!i)
l = q[i].l, r = q[i].r;
else
l = q[i - 1].r, r = q[i].r;
for(j = l; j <= r; j++) {
p[j] = lower_bound(b + 1, b + len + 1, a[j]) - b;
add(p[j], 1);
}
if(i) {
for(j = q[i - 1].l; j <= q[i].l - 1; j++)
add(p[j], -1);
for(j = q[i].r + 1; j <= q[i - 1].r; j++)
add(p[j], -1);
}
q[i].ans = b[bin(q[i].k)];
}
sort(q, q + m, cmp2);
for(i = 0; i < m; i++)
printf("%d\n", q[i].ans);
}
return 0;
}