zoukankan      html  css  js  c++  java
  • 【数据结构】可持久化线段树

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

    验证:https://www.luogu.com.cn/problem/P3919

    ver[u]表示版本u的线段树根的位置。
    所有的public操作都产生一个新的版本。

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

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

    可以修改sum操作变成不再加入新版本。

    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 ver[MAXM], cur;
    
        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;
    
  • 相关阅读:
    [转]十个让你变成糟糕的程序员的行为
    [转]CKEDITOR 使用说明
    [转]惹恼程序员的十件事
    基本权限管理框架配套代码生成器!
    Easy UI 点击TAB 标签 刷新内容
    jQuery.easyui 与 jQuery.Valiedate 验证控件组合使用实例!
    [转]十条不错的编程观点
    dos 改 ip
    今天碰到了几个老同学,哎,,感觉
    猛玩War3中
  • 原文地址:https://www.cnblogs.com/purinliang/p/14288164.html
Copyright © 2011-2022 走看看