可持久化线段树

// 洛谷: https://www.luogu.org/problemnew/show/P3919

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e6+500;

#define lson rt->left
#define rson rt->right

struct nobe {
    int val;
    nobe *left;
    nobe *right;
    nobe () {
        val = 0;
        left = right = NULL;
    }
};

int date[maxn];
nobe *head[maxn];

void build(int l, int r, nobe* rt) {
    if (l == r) {
        rt->val = date[l];
        return ;
    }
    rt->left = new nobe();
    rt->right = new nobe();
    int m = (l + r) / 2;
    build(l, m, lson);
    build(m+1, r, rson);
}

int query(int l, int r, int id, nobe *rt) {
    if (l==id && r==id) return rt->val;
    int mid = (l + r) / 2;
    if (id <= mid) return query(l, mid, id, lson);
    return query(mid+1, r, id, rson);
}

void update(int l, int r, int id, int val, nobe *rt, nobe *nrt) {
    nrt->val = rt->val; 
    nrt->left = lson; nrt->right = rson;
    if (l==id && r==id) {
        nrt->val = val;
        return ;
    }
    int mid = (l + r) / 2;
    if (id <= mid) {
        nrt->left = new nobe();
        update(l, mid, id, val, lson, nrt->left);
    } else {
        nrt->right = new nobe();
        update(mid+1, r, id, val, rson, nrt->right);
    }
}

int main()
{
//    freopen("E:\output.txt", "w", stdout);
//    freopen("E:\input.txt", "r", stdin);
    int n, m, i, j;
    scanf("%d%d", &n, &m);
    for (i=1; i<=n; ++i) scanf("%d", date+i);
    head[0] = new nobe();
    build(1, n, head[0]);
    int vs, op, id, val;
    for (i=1; i<=m; ++i) {
        scanf("%d%d%d", &vs, &op, &id);
        if (op == 1) {
            scanf("%d", &val);
            head[i] = new nobe();
            update(1, n, id, val, head[vs], head[i]);    
        } else if (op == 2) {
            head[i] = head[vs];
            printf("%d
", query(1, n, id, head[vs]));
        }
    }
    
    return 0;
}

数组

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5+10, LOG = 20;

struct nobe {
    int lson;
    int rson;
    int sum;
}te[maxn * LOG];
int head[maxn];
int tot;

int  date[maxn];
int tdate[maxn];

int build(int l, int r) {
    int rt = tot++;
    int mid = (l + r) / 2;
    if (l != r) {
        te[rt].lson = build(l, mid);
        te[rt].rson = build(mid+1, r);
    }
    return rt;
}

inline update(int pre, int l, int r, int x) {
    int rt = tot++, mid = (l + r) / 2;
    te[rt].lson = te[pre].lson; te[rt].rson = te[pre].rson, te[rt].sum = te[pre].sum + 1;
    if (l != r) {
        if (x <= mid) te[rt].lson = update(te[pre].lson, l, mid, x);
        else te[rt].rson = update(te[pre].rson, mid+1, r, x);
    } 
    return rt;
}

inline int query(int u, int v, int l , int r, int k) {
    if (l == r) return l;
    int x = te[te[v].lson].sum - te[te[u].lson].sum, mid = (l + r) / 2;
    if (x >= k) return query(te[u].lson, te[v].lson, l, mid, k);
    else return query(te[u].rson, te[v].rson, mid+1, r, k-x);
}

int main()
{
    int t, i, m;
    int n, q, x, y, z, p;
    scanf("%d", &t);
    while (t--) {
        tot = 1;
        memset(te, 0, sizeof(te));
        memset(date, 0, sizeof(date));
        memset(tdate, 0, sizeof(tdate));
        
        scanf("%d%d", &n, &q);
        for (i=1; i<=n; ++i) {
            scanf("%d", date+i);
            tdate[i] = date[i];
        }
        sort(tdate+1, tdate+n+1);
        int lst = tdate[1];
        int m = 1;
        for (i=2; i<=n; ++i) {
            if (lst != tdate[i]) {
                lst = tdate[i];
                tdate[++m] = tdate[i];
            }
        }
        m = unique(tdate+1, tdate+n+1) - tdate - 1;
        head[0] = build(1, m);
        for (i=1; i<=n; ++i) {
            date[i] = lower_bound(tdate+1, tdate+m+1, date[i]) - tdate;
            head[i] = update(head[i-1], 1, m, date[i]);
        }
        while (q--) {
            scanf("%d%d%d", &x, &y, &z);
            p = query(head[x-1], head[y], 1, m, z);
            printf("%d
", tdate[p]);
        }
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/cgjh/p/9647490.html