【数据结构】可持久化线段树

可持久化的单点修改线段树,同时也是可持久化数组

Build的时候生成不超过2n个节点,每次修改生成不超过logn个节点。
MAXM是修改操作的上限。

规定Build完成的版本是1号版本。
无论是哪一种操作,都会记录一个新版本。

struct SegmentTree {

private:

#define ls lch[o]
#define rs rch[o]

    static const int MAXN = 1e6 + 10;
    static const int MAXM = 1e6 + 10;

    int n;

    int top;
    int lch[MAXN * 4 + MAXM * 24];
    int rch[MAXN * 4 + MAXM * 24];
    ll sum[MAXN * 4 + MAXM * 24];

    int cur;
    int ver[MAXM];

    int Clone(int o) {
        ++top;
        sum[top] = sum[o];
        lch[top] = ls;
        rch[top] = rs;
        return top;
    }

    void PushUp(int o) {
        sum[o] = sum[ls] + sum[rs];
    }

    int BuildHelp(int l, int r) {
        int o = Clone(0);
        if(l == r) {
            sum[o] = a[l];
            ls = 0;
            rs = 0;
            return o;
        }
        int m = (l + r) >> 1;
        ls = BuildHelp(l, m);
        rs = BuildHelp(m + 1, r);
        PushUp(o);
        return o;
    }

    int AddHelp(int o, int l, int r, int p, ll v) {
        o = Clone(o);
        if(l == r) {
            sum[o] += v;
            return o;
        }
        int m = (l + r) >> 1;
        if(p <= m)
            ls = AddHelp(ls, l, m, p, v);
        if(p >= m + 1)
            rs = AddHelp(rs, m + 1, r, p, v);
        PushUp(o);
        return o;
    }

    int SetHelp(int o, int l, int r, int p, ll v) {
        o = Clone(o);
        if(l == r) {
            sum[o] = v;
            return o;
        }
        int m = (l + r) >> 1;
        if(p <= m)
            ls = SetHelp(ls, l, m, p, v);
        if(p >= m + 1)
            rs = SetHelp(rs, m + 1, r, p, v);
        PushUp(o);
        return o;
    }

    ll SumHelp(int o, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr)
            return sum[o];
        int m = (l + r) >> 1;
        ll res = 0;
        if(ql <= m)
            res = res + SumHelp(ls, l, m, ql, qr);
        if(qr >= m + 1)
            res = res + SumHelp(rs, m + 1, r, ql, qr);
        return res;
    }

public:

    void Build(int _n) {
        n = _n;
        cur = 0;
        top = 0;
        ver[cur] = BuildHelp(1, n);
    }

    void Add(int id, int pos, int val) {
        ver[++cur] = AddHelp(ver[id], 1, n, pos, val);
    }

    void Set(int id, int pos, int val) {
        ver[++cur] = SetHelp(ver[id], 1, n, pos, val);
    }

    ll Sum(int id, int lpos, int rpos) {
        ll res = SumHelp(ver[id], 1, n, lpos, rpos);
        ver[++cur] = ver[id];
        return res;
    }

} st;
上一篇:25、邻接表:有向无环图(DAG)的判断


下一篇:通信线路【最短路】