[洛谷P3834] 【模板】可持久化线段树 1(主席树)
题目大意:静态区间第K小
题解:主席树
卡点:无
C++ Code:
#include <cstdio>
#include <algorithm>
#define maxn 200010
#define maxm 12000010
using namespace std;
int rt[maxn], lc[maxm], rc[maxm], num[maxm], idx;
int n, m, x, y, k;
int s[maxn], rnk[maxn], p[maxn];
inline bool cmp (int a,int b){return s[a] < s[b];}
void add(int &cur, int ver, int l, int r, int x) {
cur = ++idx;
lc[cur] = lc[ver]; rc[cur] = rc[ver], num[cur] = num[ver] + 1;
if (l ^ r) {
int mid = l + r >> 1;
if (x <= mid) add(lc[cur], lc[ver], l, mid, x);
else add(rc[cur], rc[ver], mid + 1, r, x);
}
}
int ask(int L, int R, int l, int r, int k) {
if (l == r) return s[rnk[l]];
int t = num[lc[R]] - num[lc[L]], mid = l + r >> 1;
if (k <= t) return ask(lc[L], lc[R], l, mid, k);
else return ask(rc[L], rc[R], mid + 1, r, k - t);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)scanf("%d", &s[i]), rnk[i] = i;
sort(rnk + 1, rnk + n + 1, cmp);
for (int i = 1; i <= n; i++) p[rnk[i]] = i;
for (int i = 1; i <= n; i++) rt[i] = rt[i - 1], add(rt[i], rt[i - 1], 1, n, p[i]);
while (m--) {
scanf("%d%d%d", &x, &y, &k);
printf("%d\n", ask(rt[x - 1], rt[y], 1, n, k));
}
return 0;
}

浙公网安备 33010602011771号