CP Notebook

← all snippets

PersSegmentTree

Adds a time dimension to the segment tree. This is mostly an example implementation of a persistent segment tree. It would likely be better to instead modify the implementations of the other segment trees to be persistent.

Time: O(n log n) 38 lines lightly tested

Usage: roots[ind++] = build(0, n-1, a); to build, roots[ind] = update(roots[ind], pos, new_val, 0, n-1); to update, ll sum = query(roots[ind], l, r, 0, n-1); to query, and roots[ind++] = new segtree(roots[old_ind]); to copy a version.

content/data-structures/PersSegmentTree.h — unknown, source: unknown

int ind = 0;
struct segtree {
    ll val;
    segtree *left, *right;

    segtree(ll x) : val(x), left(nullptr), right(nullptr) {;;}

    segtree(segtree *left, segtree *right) : left(left), right(right) {
        val = 0;
        if (left) val += left->val;
        if (right) val += right->val;
    }

    segtree(segtree *copy) : val(copy->val), left(copy->left), right(copy->right) {;;}
};

segtree *build(int l, int r, vector<ll> &a) {
    if (l == r) return new segtree(a[l]);
    int m = (l + r) / 2;
    return new segtree(build(l, m, a), build(m+1, r, a));
}

segtree *update(segtree *curr, int ind, ll upd, int l, int r) {
    if (l == r) return new segtree(upd);
    int m = (l + r) / 2;
    if (ind <= m) return new segtree(update(curr->left, ind, upd, l, m), curr->right);
    else return new segtree(curr->left, update(curr->right, ind, upd, m+1, r));
}

ll query(segtree *curr, int ql, int qr, int l, int r) {
    if (ql > r or qr < l) return 0;
    if (ql <= l and r <= qr) return curr->val;
    int m = (l + r) / 2;
    return query(curr->left, ql, qr, l, m) + query(curr->right, ql, qr, m+1, r);
}

const int MAXN = 2e5+5;
segtree *roots[MAXN];