求区间第K大
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
struct CT{
static const int MAXN = 1e5 + 5;
static const int TIME = 20;
int tot;
int T[MAXN * TIME], LT[MAXN * TIME], RT[MAXN * TIME], SUM[MAXN * TIME];
void T_init(){
tot = 0;
}
void build(int &o, int l, int r){
o = ++ tot;
SUM[o] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(LT[o], l, mid);
build(RT[o], mid + 1, r);
}
void update(int &o, int l, int r, int last, int p){
o = ++ tot;
LT[o] = LT[last];
RT[o] = RT[last];
SUM[o] = SUM[last] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) update(LT[o], l, mid, LT[last], p);
else update(RT[o], mid + 1, r, RT[last], p);
}
int query(int nl, int nr, int l, int r, int k){
if(l == r) return l;
int mid = (l + r) >> 1;
int lsum = SUM[LT[nr]] - SUM[LT[nl]];
if(k <= lsum) return query(LT[nl], LT[nr], l, mid, k);
else return query(RT[nl], RT[nr], mid + 1, r, k - lsum);
}
}ST;
int n, m;
int A[CT::MAXN], B[CT::MAXN];
int main(){
while(~scanf("%d%d", &n, &m)){
for(int i = 1;i <= n;i ++){
scanf("%d", &A[i]);
B[i] = A[i];
}
sort(B + 1, B + n + 1);
int sz = unique(B + 1, B + n + 1) - B - 1;
ST.T_init();
ST.build(ST.T[0], 1, sz);
for(int i = 1;i <= n;i ++){
A[i] = lower_bound(B + 1, B + sz + 1, A[i]) - B;
}
for(int i = 1;i <= n;i ++){
ST.update(ST.T[i], 1, sz, ST.T[i - 1], A[i]);
}
int a, b, k;
while(m --){
scanf("%d%d%d", &a, &b, &k);
if(b < a) swap(a, b);
int idx = ST.query(ST.T[a - 1], ST.T[b], 1, sz, k);
printf("%d\n", B[idx]);
}
}
}