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

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\n", root.Rank(y)); break;
            case 4: printf("%d\n", root.Kth(y)); break;
            case 5: printf("%d\n", root.Kth(root.Rank(y)-1)); break;
            case 6: printf("%d\n", root.Kth(root.Rank(y+1))); break;
        }
    }
}

 

posted @ 2016-11-21 18:44  Saurus  阅读(590)  评论(0编辑  收藏  举报