在区间[l, r]内查询从小到大,排在第K的数,就是一个主席树的模板题
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <bitset>
#define INF 0x3f3f3f3f
#define eps 1e-6
#define PI 3.1415926
#define mod 1000000009
#define base 2333
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int maxx = 1e3 + 10;
inline void splay(int &v) {
v=0;char c=0;int p=1;
while(c<'0' || c >'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int n, m, l, r, k, cnt, a[maxn], b[maxn], T[maxn];
int L[maxn<<5], R[maxn<<5], sum[maxn<<5];
int build(int l, int r) {
int id = ++cnt;
sum[id] = 0;
if(l < r) {
int m = (l+r)>>1;
L[id] = build(l, m);
R[id] = build(m+1, r);
}
return id;
}
int update(int pre, int l, int r, int x) {
int id = ++cnt;
L[id] = L[pre], R[id] = R[pre], sum[id] = sum[pre]+1;
if(l < r) {
int m = (l+r)>>1;
if(x <= m) L[id] = update(L[pre], l, m, x);
else R[id] = update(R[pre], m+1, r, x);
}
return id;
}
int query(int u, int v, int l, int r, int k) {
if(l >= r) return l;
int m = (l+r)>>1;
int num = sum[L[v]]-sum[L[u]];
if(num >= k)
return query(L[u], L[v], l, m, k);
else
return query(R[u], R[v], m+1, r, k-num);
}
void solve() {
splay(n), splay(m);
cnt = 0;
for(int i = 1; i <= n; i++) {
splay(a[i]);
b[i] = a[i];
}
sort(b+1, b+n+1);
int d = unique(b+1, b+n+1)-b-1;
T[0] = build(1, d);
for(int i = 1; i <= n; i++) {
int x = lower_bound(b+1, b+d+1, a[i])-b;
T[i] = update(T[i-1], 1, d, x);
}
while(m--) {
splay(l), splay(r), splay(k);
int ans = query(T[l-1], T[r], 1, d, k);
printf("%d\n", b[ans]);
}
}
int main() {
//srand(time(NULL));
//freopen("kingdom.in","r",stdin);
//freopen("kingdom.out","w",stdout);
solve();
}