可持久化线段树

【模板】可持久化线段树 2(主席树)

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
using namespace std;

const int N = 2e5 + 5;

int n, q, a[N], b[N];

int head[N], lson[N << 5], rson[N << 5], sum[N << 5], cnt;

int build(int l, int r) {
    int rt = ++cnt;
    if (l == r) return rt;
    lson[rt] = build(l, mid);
    rson[rt] = build(mid + 1, r);
    return rt;
}

int modify(int pre, int l, int r, int pos) {
    int rt = ++cnt;
    sum[rt] = sum[pre] + 1;
    lson[rt] = lson[pre]; rson[rt] = rson[pre];
    if (l == r) return rt;
    if (pos <= mid) lson[rt] = modify(lson[pre], l, mid, pos);
    else rson[rt] = modify(rson[pre], mid + 1, r, pos);
    return rt;
}

int query(int rtx, int rty, int l, int r, int k) {
    if (l == r) return l;

    int x = sum[lson[rty]] - sum[lson[rtx]];
    if (x >= k) return query(lson[rtx], lson[rty], l, mid, k);
    else return query(rson[rtx], rson[rty], mid + 1, r, k - x);
}

int main() {
    scanf("%d %d", &n, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        b[i] = a[i];
    }
    sort(b + 1, b + 1 + n);
    int m = unique(b + 1, b + 1 + n) - b - 1;
    head[0] = build(1, m);
    for (int i = 1; i <= n; i++) {
        int pos = lower_bound(b + 1, b + 1 + m, a[i]) - b;
        head[i] = modify(head[i - 1], 1, m, pos);
    }
    while(q--) {
        int x, y, k; scanf("%d %d %d", &x, &y, &k);
        int t = query(head[x - 1], head[y], 1, m, k);
        printf("%d\n", b[t]);
    }
    return 0;
}