• Treap(树堆)


    一、Treap简介

    Treap 是一种具有堆性质的二叉搜索树
    原理:为每一个结点赋予一个随机值使其满足堆的性质,
    保证树高度在O(logN)左右,以此保证较低的时间复杂度

    Treap和set比较
    Treap比set更好实现
    Treap更易于处理类似第K性质的求解问题,而set实现起来稍逊一筹
    综上述,Treap常用于算法竞赛需要手写BST的时候,尤其是名次树

    二、实现

    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxNode = 1<<15;
    const int INF = 0x3f3f3f3f;
    
    class Treap
    {
        int root, treapCnt, key[maxNode], priority[maxNode], childs[maxNode][2], cnt[maxNode], size[maxNode];
    
        int rand()
        {
            static int seed = 2333;
            return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
        }
    
        //旋转
        void rotate(int& x, int t)
        {
            int y = childs[x][t];
            childs[x][t] = childs[y][1 - t];
            childs[y][1 - t] = x;
            update(x);
            update(y);
            x = y;
        }
    
        //更新规模大小
        void update(const int x)
        {
            size[x] = size[childs[x][0]] + cnt[x] + size[childs[x][1]];
        }
    
        //插入k值
        void _insert(int& x, const int k)
        {
            if (x)
            {
                if (key[x] == k)
                {
                    cnt[x]++;                   //如果该键值存在,那么数量+1
                }
                else
                {
                    bool t = key[x] < k;         //判断k应属的子树
                    _insert(childs[x][t], k);
                    if (priority[childs[x][t]] < priority[x])
                    {
                        rotate(x, t);
                    }
                }
            }
            else
            {
                x = treapCnt++;
                key[x] = k;
                cnt[x] = 1;
                priority[x] = rand();
                childs[x][0] = childs[x][1] = 0;
            }
            update(x);
        }
    
        void _erase(int& x, const int k)
        {
            if (key[x] == k)
            {
                if (cnt[x] > 1)
                    cnt[x]--;
                else
                {
                    if (childs[x][0] == 0 && childs[x][1] == 0)
                    {
                        x = 0;
                        return;
                    }
                    int t = priority[childs[x][0]] > priority[childs[x][1]];
                    rotate(x, t);
                    _erase(x, k);
                }
            }
            else
            {
                _erase(childs[x][key[x] < k], k);
            }
            update(x);
        }
    
        int _getKth(int& x, int k, const bool ismax)
        {
            if (k <= size[childs[x][ismax]])
            {
                return _getKth(childs[x][ismax], k, ismax);
            }
            k -= size[childs[x][ismax]] + cnt[x];
            if (k <= 0)
                return key[x];
            return _getKth(childs[x][!ismax], k, ismax);
        }
    
        int _findRank(const int p, const int x)
        {
            if (!p)return 0;
            if (key[p] == x)return size[childs[p][0]] + 1;
            if (x > key[p])return size[childs[p][0]] + cnt[p] + _findRank(childs[p][1], x);
            else return _findRank(childs[p][0], x);
        }
    
        int _findBack(const int p, const int x)
        {
            if (!p)return -INF;
            if (key[p] < x)return max(key[p], _findBack(childs[p][1], x));
            else if (key[p] >= x)return _findBack(childs[p][0], x);
        }
    
        int _findFront(const int p, const int x)
        {
            if (!p)return INF;
            if (key[p] <= x)return _findFront(childs[p][1], x);
            else return min(key[p], _findFront(childs[p][0], x));
        }
    public:
    
        Treap()
        {
            root = 0;
            treapCnt = 1;
            priority[0] = INF;
            size[0] = 0;
        }
    
        //插入键值k
        void insert(const int k)
        {
            _insert(root, k);
        }
    
        //删除键值k
        void erase(const int k)
        {
            _erase(root, k);
        }
    
        //查询 K-th
        int getKth(const int k, const bool ismax)
        {
            return _getKth(root, k, ismax);
        }
    
        //查询x的排名
        int find_rank(const int x)
        {
            return _findRank(root, x);
        }
    
        //查询键值x的前驱
        int find_back(const int x)
        {
            return _findBack(root, x);
        }
    
        //查询键值x的后继
        int find_front(const int x)
        {
            return _findFront(root, x);
        }
    };
    
  • 相关阅读:
    GDB常用命令
    codevs1743
    Codeforces Round #369 (Div. 2)E
    Codeforces Round #200 (Div. 2)E
    2016 Multi-University Training Contest 4 T9
    2016 Multi-University Training Contest 1 T3
    2016 Multi-University Training Contest 1 T4
    HDU 5448 Marisa’s Cake
    codeforces 467C George and Job dp
    poj 1704 Georgia and Bob 博弈
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9386974.html
Copyright © 2020-2023  润新知