zoukankan      html  css  js  c++  java
  • 【算法

    代码

    /* Treap : 完整版 */
    struct Treap {
       private:
        static const int TREAP_MAXN = 2e5 + 5;
        static const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
        int root, top, del[TREAP_MAXN];
        int ch[TREAP_MAXN][2], rnd[TREAP_MAXN];
    
       public:
        ll cnt[TREAP_MAXN], siz[TREAP_MAXN];
        ll val[TREAP_MAXN], sum[TREAP_MAXN];
    
       private:
    #define ls ch[u][0]
    #define rs ch[u][1]
        int NewNode(ll v, ll c) {
            int u = del[0] ? (del[del[0]--]) : ++top;
            ls = rs = 0, rnd[u] = rand();
            cnt[u] = siz[u] = c;
            val[u] = v, sum[u] = c * v;
            return u;
        }
        void PushUp(int u) {
            siz[u] = siz[ls] + siz[rs] + cnt[u];
            sum[u] = sum[ls] + sum[rs] + cnt[u] * val[u];
        }
        void Rotate(int &u, int d) {
            int t = ch[u][d ^ 1];
            ch[u][d ^ 1] = ch[t][d], ch[t][d] = u, u = t;
            PushUp(ch[u][d]), PushUp(u);
        }
        void InsertHelp(int &u, ll v, ll c) {
            if (!u) {
                u = NewNode(v, c);
                return;
            } else if (v == val[u]) {
                cnt[u] += c;
            } else {
                int d = val[u] < v;
                InsertHelp(ch[u][d], v, c);
                if (rnd[u] < rnd[ch[u][d]]) Rotate(u, d ^ 1);
            }
            PushUp(u);
        }
        void RemoveHelp(int &u, ll v, ll c) {
            if (!u) {
                return;
            } else if (v == val[u]) {
                if (cnt[u] > c) {
                    cnt[u] -= c;
                } else if (ls || rs) {
                    int d = (!rs || rnd[ls] > rnd[rs]);
                    Rotate(u, d), RemoveHelp(ch[u][d], v, c);
                } else {
                    del[++del[0]] = u, u = 0;
                    return;
                }
            } else {
                RemoveHelp(ch[u][val[u] < v], v, c);
            }
            PushUp(u);
        }
        ll GetRankHelp(int u, ll v) {
            if (!u) {
                return 0;
            } else if (val[u] == v) {
                return siz[ls];
            } else if (val[u] > v) {
                return GetRankHelp(ls, v);
            } else {
                return siz[ls] + cnt[u] + GetRankHelp(rs, v);
            }
        }
        ll GetValueHelp(int u, ll r) {
            if (!u) {
                return LINF;
            } else if (siz[ls] < r && siz[u] - siz[rs] >= r) {
                return val[u];
            } else if (siz[ls] >= r) {
                return GetValueHelp(ls, r);
            } else {
                return GetValueHelp(rs, r - siz[u] + siz[rs]);
            }
        }
        ll GetPrevHelp(int u, ll v) {
            if (!u) {
                return -LINF;
            } else if (val[u] < v) {
                return max(val[u], GetPrevHelp(rs, v));
            } else {
                return GetPrevHelp(ls, v);
            }
        }
        ll GetNextHelp(int u, ll v) {
            if (!u) {
                return LINF;
            } else if (val[u] > v) {
                return min(val[u], GetNextHelp(ls, v));
            } else {
                return GetNextHelp(rs, v);
            }
        }
        ll GetSumValueHelp(int u, ll v) {
            if (!u) {
                return 0;
            } else if (val[u] == v) {
                return sum[u] - sum[rs];
            } else if (val[u] > v) {
                return GetSumValueHelp(ls, v);
            } else {
                return sum[u] - sum[rs] + GetSumValueHelp(rs, v);
            }
        }
        ll GetSumRankHelp(int u, ll r) {
            if (!u) {
                return 0;
            } else if (siz[ls] < r && siz[u] - siz[rs] >= r) {
                return sum[ls] + (r - siz[ls]) * val[u];
            } else if (siz[ls] >= r) {
                return GetSumRankHelp(ls, r);
            } else {
                return sum[u] - sum[rs] + GetSumRankHelp(rs, r - siz[ls] + cnt[u]);
            }
        }
    #undef ls
    #undef rs
    
       public:
        void Init() { top = 0, root = 0; }
        void Insert(ll v, ll c = 1) { InsertHelp(root, v, c); }
        void Remove(ll v, ll c = 1) { RemoveHelp(root, v, c); }
        ll GetRank(ll v) { return GetRankHelp(root, v) + 1; }
        ll GetValue(ll r) { return GetValueHelp(root, r); }
        ll GetPrev(ll v) { return GetPrevHelp(root, v); }
        ll GetNext(ll v) { return GetNextHelp(root, v); }
        ll GetSumValue(ll v) { return GetSumValueHelp(root, v); }
        ll GetSumRank(ll r) { return GetSumRankHelp(root, r); }
    } treap;
    

    使用说明

    节点:指Treap的节点,代码中用u表示
    元素:指val中存储的值,代码中用v表示

    注意区分节点和元素的区别。在这个实现中,节点和元素的权值是一一对应的,相同权值的元素会累计到同一个节点内。

    以下字段可能涉及扩展性,可能需要修改:

    TREAP_MAXN;  // Treap能容纳的最大节点数
    LINF;        // 元素权值的正无穷大
    cnt[u];      // 节点u表示的元素数量
    siz[u];      // 节点u的子树的元素数量和
    val[u];      // 节点u表示的元素权值
    sum[u];      // 节点u的子树的元素权值和
    
    // 以下“排名”定义为<v的元素数量+1,为正整数
    int NewNode(ll v, ll c);               // 新建一个节点,表示c个权值为v的元素
    void PushUp(int u);                    // 重新计算节点u的信息
    void InsertHelp(int &u, ll v, ll c);   // 向节点u的子树插入c个权值为v的元素
    void RemoveHelp(int &id, ll v, ll c);  // 从节点u的子树删除至多c个权值为v的元素
    ll GetRankHelp(int u, ll v);           // 查询节点u的子树中权值为v的元素的排名-1
    ll GetValueHelp(int u, ll r);          // 查询节点u的子树中排名为r的元素的权值,若不存在返回LINF
    ll GetPrevHelp(int u, ll v);           // 查询节点u的子树中<v的元素的权值的最大值,若不存在返回-LINF
    ll GetNextHelp(int u, ll v);           // 查询节点u的子树中>v的元素的权值的最小值,若不存在返回LINF
    ll GetSumValueHelp(int u, ll v);       // 查询节点u的子树中权值<=v的元素的权值和
    ll GetSumRankHelp(int u, ll r);        // 查询节点u的子树中排名<=r的元素的权值和
    
    void Init();                           // 初始化Treap,清空所有节点和回收栈
    void Insert(ll v, ll c);               // 向Treap插入c个权值为v的元素
    void Remove(ll v, ll c);               // 从Treap删除至多c个权值为v的元素
                                           
    ll GetRank(ll v);                      // 查询Treap中权值为v的元素的排名
    ll GetValue(ll r);                     // 查询Treap中排名为r的元素的权值
    ll GetPrev(ll v);                      // 查询Treap中权值为v的元素的前驱节点的元素的权值,若不存在返回-LINF
    ll GetNext(ll v);                      // 查询Treap中权值为v的元素的后继节点的元素的权值,若不存在返回LINF
    ll GetSumValue(ll v);                  // 查询Treap中权值<=v的元素的权值和
    ll GetSumRank(ll r);                   // 查询Treap中排名<=r的元素的权值和
    

    注意:这里为了方便,新建节点时使用了rand(),这会导致不同平台上运行结果很可能会有差异!


    评价

    性能特点:

    1. 在线算法
    2. 时间复杂度基于元素数量,且为期望复杂度
    3. 空间复杂度基于元素数量
    4. 运行的常数较小
    5. 使用懒标记维护较简洁
    6. 带旋转操作,不能可持久化
    7. 不像其他数据结构拥有无法取代的“特长”,不同场景下都可以被替代,甚至可以不学

    与Splay对比:
    Treap一般情况下常数较小,维护较简洁,时间复杂度为期望复杂度,但不能维护序列操作,也不支持LCT

    与动态开点权值线段树和01Trie对比:
    Treap的时间复杂度和空间复杂度都与值域无关,一般而言节省至少30%,但是不能维护异或操作,也不方便可持久化

  • 相关阅读:
    将博客搬至CSDN
    vector iterator not incrementable For information on how your program can cause an an assertion Failure, see the Visual c + + documentation on asserts
    VS2013+opencv2.4.9配置
    数组去重排序
    堆排序理解 完整代码
    dijkstra 两点的最短路径 单源 最短路径
    欧拉回路
    next 前缀字符串
    继续畅通工程
    sql server转移tempdb数据库的物理存放位置
  • 原文地址:https://www.cnblogs.com/purinliang/p/14265149.html
Copyright © 2011-2022 走看看