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

P3834 【模板】可持久化线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

template<class Node>
struct PersidentSegmentTree {
#define lc(u) tr[u].l
#define rc(u) tr[u].r
#define sum(u) tr[u].s
    const int n;
    int tot = 0;
    vector<Node> tr;
    vector<int> root;

    PersidentSegmentTree(): n(0) {}

    PersidentSegmentTree(int n_): n(n_) {
        int N = (n << 7) + 10;
        tr.reserve(N); root.reserve(N);
        tr.resize(N); root.resize(N);

        function<void(int&, int, int)> build = [&](int& u, int l, int r) {
            u = ++ tot;
            sum(u) = 0;
            if (l == r) {javascript:void(0);
                return ;
            }
            int m = (l + r) >> 1;
            build(lc(u), l, m);
            build(rc(u), m + 1, r);
        };
        build(root[0], 1, n);
    }

    void insert(int u, int& v, int l, int r, int pos) {
        v = ++ tot;
        tr[v] = tr[u], sum(v) = sum(u) + 1;
        if (l == r)
            return;
        int m = l + r >> 1;
        if (pos <= m)
            insert(lc(u), lc(v), l, m, pos);
        else
            insert(rc(u), rc(v), m + 1, r, pos);
    }

    int query(int u, int v, int l, int r, int k) {
        if (l == r)
            return l;

        int m = l + r >> 1, s = sum(lc(v)) - sum(lc(u));
        if (k <= s)
            return query(lc(u), lc(v), l, m, k);
        else
            return query(rc(u), rc(v), m + 1, r, k - s);
    }
};

struct Node {
    int l, r, s;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;

    vector<int> b(n + 1);
    for (int i = 1; i <= n; i ++)
        cin >> b[i];

    auto a = b;
    sort(a.begin() + 1, a.end());
    int m = unique(a.begin() + 1, a.end()) - a.begin() - 1;

    PersidentSegmentTree<Node> PST(m);

    for (int i = 1; i <= n; i ++) {
        int idx = lower_bound(a.begin() + 1, a.begin() + m + 1, b[i]) - a.begin();
        PST.insert(PST.root[i - 1], PST.root[i], 1, m, idx);
    }

    while (q--) {
        int l, r, k;
        cin >> l >> r >> k;
        int idx = PST.query(PST.root[l - 1], PST.root[r], 1, m, k);
        cout << a[idx] << '\n';
    }

    return 0;
}
posted @ 2024-08-07 19:41  Ke_scholar  阅读(4)  评论(0编辑  收藏  举报