• 替罪羊树模板(封装版)-----转自知乎


    https://zhuanlan.zhihu.com/p/21263304

    里面有关于替罪羊树的详细介绍,这里就不再赘述。

    #include <vector>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    namespace Scapegoat_Tree
    {
        #define MAXN (100000 + 10)
        const double alpha = 0.75;
        struct Node
        {
            Node *ch[2];
            int key, sz, cover;
            bool exist;
            void pushup()
            {
                sz = ch[0]->sz + ch[1]->sz + (int)exist;
                cover = ch[0]->cover + ch[1]->cover + 1;
            }
            bool isbad()
            {
                return (ch[0]->cover > cover * alpha + 5)||
                        (ch[1]->cover > cover * alpha + 5);
            }
        };
        struct STree
        {
        protected:
            Node mem_poor[MAXN];
            Node *tail, *root, *null;
            Node *bc[MAXN];
            int bc_top;
    
            Node * Newnode(int key)
            {
                Node *p = bc_top ? bc[--bc_top] : tail++;
                p->ch[0] = p->ch[1] = null;
                p->sz = p->cover = 1; p->exist = true;
                p->key = key;
                return p;
            }
            void Travel(Node *p, vector<Node *> &v)
            {
                if(p == null) return;
                Travel(p->ch[0], v);
                if(p->exist) v.push_back(p);
                else bc[bc_top++] = p;
                Travel(p->ch[1], v);
            }
            Node* Divide(vector<Node *> &v, int l, int r)
            {
                if(l >= r) return null;
                int mid = (l+r)>>1;
                Node *p = v[mid];
                p->ch[0] = Divide(v, l, mid);
                p->ch[1] = Divide(v, mid+1, r);
                p->pushup();
                return p;
            }
            void Rebuild(Node *& p)
            {
                static vector<Node *>v; v.clear();
                Travel(p, v); p = Divide(v, 0, v.size());
            }
            Node ** Insert(Node *&p, int val)
            {
                if(p == null)
                {
                    p = Newnode(val);
                    return &null;
                }
                else
                {
                    p->sz++; p->cover++;
                    Node **res = Insert(p->ch[val >= p->key], val);
                    if(p->isbad()) res = &p;
                    return res;
                }
            }
            void Erase(Node *p, int id)
            {
                p->sz--;
                int offset = p->ch[0]->sz + p->exist;
                if(p->exist && id == offset)
                {
                    p->exist = false;
                    return;
                }
                else
                {
                    if(id <= offset) Erase(p->ch[0], id);
                    else Erase(p->ch[1], id - offset);
                }
            }
        public:
            void init()
            {
                tail = mem_poor;
                null = tail++;
                null->ch[0] = null->ch[1] = null;
                null->cover = null->sz = null->key = 0;
                root = null; bc_top = 0;
            }
            void Insert(int val)
            {
                Node **p = Insert(root, val);
                if(*p != null) Rebuild(*p);
            }
            int Rank(int val)
            {
                Node *now = root;
                int ans = 1;
                while(now != null)
                {
                    if(now->key >= val) now = now->ch[0];
                    else
                    {
                        ans += now->ch[0]->sz + now->exist;
                        now = now->ch[1];
                    }
                }
                return ans;
            }
            int Kth(int k)
            {
                Node *now = root;
                while(now != null)
                {
                    if(now->ch[0]->sz + 1 == k && now->exist) return now->key;
                    else if(now->ch[0]->sz >= k) now = now->ch[0];
                    else k -= now->ch[0]->sz + now->exist, now = now->ch[1];
                }
                return 0;
            }
            void Erase(int k)
            {
                Erase(root, Rank(k));
                if(root->sz < alpha*root->cover) Rebuild(root);
            }
            void Erase_kth(int k)
            {
                Erase(root, k);
                if(root->sz < alpha * root->cover) Rebuild(root);
            }
        };
        #undef MAXN
    }
    using namespace Scapegoat_Tree;
    STree root;
    int main()
    {
        int T, x, y; cin>>T; root.init();
        while(T--)
        {
            scanf("%d %d", &x, &y);
            switch(x)
            {
                case 1: root.Insert(y); break;
                case 2: root.Erase(y); break;
                case 3: printf("%d
    ", root.Rank(y)); break;
                case 4: printf("%d
    ", root.Kth(y)); break;
                case 5: printf("%d
    ", root.Kth(root.Rank(y)-1)); break;
                case 6: printf("%d
    ", root.Kth(root.Rank(y+1))); break;
            }
        }
    }
  • 相关阅读:
    C#下水晶报表打印自定义纸张
    设计模式应用之一:控件清空
    自定义StyleCop规则
    1.redis安装 单机
    dubbo个人总结
    spring+redis 集群下的操作
    mybatis调用存储过程 无参、带有输入输出参数,输出游标类型的 存储
    spring framework核心框架体系结构
    oracle‘s package,function,proceture编译时无响应(解决)
    Oracle 在线重定义表分区
  • 原文地址:https://www.cnblogs.com/Saurus/p/6086509.html
Copyright © 2020-2023  润新知