zoukankan      html  css  js  c++  java
  • 红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

    二次联通门 : luogu P3369 【模板】普通平衡树(Treap/SBT)

    近几天闲来无事。。。就把各种平衡树都写了一下。。。

    下面是红黑树(Red Black Tree)

    喜闻乐见拿到了luogu,COGS的rank1

    QAQ rank1没啦!!!被树状数组艹啦!!!

     10.11 Updata 压了压行233333

    #include <cstdio>
    #include <iostream>
    #define Max 100001
    #define Red true
    #define Black false
    const int BUF = 100000100; char Buf[BUF], *buf = Buf;
    #define rg register
    #define Inline __attri
    bute__( ( optimize( "-O2" ) ) )
    Inline void read (int &n)
    {
        bool temp = false;
        for (n = 0; !isdigit (*buf); ++ buf) if (*buf == '-') temp = true;
        for (; isdigit (*buf); n = n * 10 + *buf - '0', ++ buf);
        if (temp) n = -n;
    }
    struct RD
    {
        int v, _s, _w; bool _c; RD *f, *c[2];
        Inline void Fill (const int &_v, const bool &__c, const int &z, rg RD *n)
        { v = _v, _c = __c, _s = _w = z, f = c[0] = c[1] = n; }
        Inline void Up () { _s = c[0]->_s + c[1]->_s + _w; }
        Inline void dn ()
        { for (RD *n = this; n->_s; n = n->f) -- n->_s; }
        Inline int Get_Pos (const int &n) { return this->v == n ? -1 : n > v; } 
    };
    class Red_Black_Tree
    {
        private : int _t; RD *Rt, *null, poor[Max], *Tail, *reuse[Max];
        private :
          
            Inline RD *New (const int &v)
            {
                rg RD *n = null;
                if (!_t) n = Tail ++; else n = reuse[-- _t];
                n->Fill (v, Red, 1, null);
                return n;
            }
            
            Inline void R (RD *&n, const bool &_p)
            {
                rg RD *C = n->c[_p ^ 1];
                n->c[_p ^ 1] = C->c[_p];
                if (C->c[_p]->_s) C->c[_p]->f = n;
                C->f = n->f; if (!n->f->_s) Rt = C;
                else  n->f->c[n->f->c[0] != n] = C;
                C->c[_p] = n; n->f = C; C->_s = n->_s; n->Up ();
            }
            
            Inline void If (rg RD *&n)
            {
                for (; n->f->_c; )
                {
                    RD *_F = n->f, *_g = _F->f;
                    bool _p = _F == _g->c[0]; RD *_u = _g->c[_p];
                    if (_u->_c) _F->_c = _u->_c = Black, _g->_c = Red, n = _g;
                    else if (n == _F->c[_p]) R (n = _F, _p ^ 1);
                    else _g->_c = Red, _F->_c = Black, R (_g, _p);
                }
                Rt->_c = Black;
            }
            
            Inline RD *Find (RD *n, int v)
            {
                for (; n->_s && n->v != v; n = n->c[n->v < v]);
                return n;
            }
            
            Inline void Df (rg RD *&n)
            {
                for (; n != Rt && n->_c == Black; )
                {
                    rg bool _p = n == n->f->c[0];
                    RD *_F = n->f, *_u = _F->c[_p];
                    if (_u->_c == Red)
                        _u->_c = Black, _F->_c = Red, R (n->f, _p ^ 1), _u = _F->c[_p];
                    else if (_u->c[0]->_c == Black && _u->c[1]->_c == Black)
                        _u->_c = Red, n = _F;
                    else
                    {
                        if (_u->c[_p]->_c == Black)
                            _u->c[_p ^ 1]->_c = Black, _u->_c = Red, R (_u, _p), _u = _F->c[_p];
                        _u->_c = _F->_c, _u->c[_p]->_c = _F->_c = Black, R (_F, _p ^ 1);
                        break;
                    }
                }
                n->_c = Black;
            }
            
        public :
            
            Red_Black_Tree ()
            {
                _t = 0, Tail = &poor[_t];
                null = Tail ++, null->Fill (0, Black, 0, NULL), Rt = null;
            }
            
            Inline void Insert (const int &v)
            {
                rg RD *n = Rt, *_F = null;
                rg int _p;
                for (; n->_s; n = n->c[_p])
                {
                    ++ n->_s, _F = n, _p = n->Get_Pos (v);
                    if (_p == -1) { ++ n->_w; return ; }
                }
                n = New (v); 
                if (_F->_s) _F->c[v > _F->v] = n; else Rt = n;
                n->f = _F; If (n); 
            }
            
            Inline void Delete (const int &v)
            {
                rg RD *_r = Find (Rt, v);
                if (!_r->_s) return ;
                if (_r->_w > 1) { -- _r->_w, _r->dn (); return ; }
                rg RD *_F = _r, *n = null;
                if (_r->c[0]->_s && _r->c[1]->_s)
                    for (_F = _r->c[1]; _F->c[0]->_s; _F = _F->c[0]);
                n = _F->c[!_F->c[0]->_s], n->f = _F->f;
                if (!_F->f->_s) Rt = n;
                else _F->f->c[_F->f->c[1] == _F] = n;
                if (_r != _F) _r->v = _F->v, _r->_w = _F->_w;
                _F->f->dn ();
                for (RD *p = _F->f; _F->_w > 1 && p->_s && p != _r; p->_s -= _F->_w - 1, p = p->f);
                if (_F->_c == Black) Df (n);
                reuse[_t ++] = _F;
            }
            
            Inline int Get_kth_number (rg int k)
            {
                rg int _r; rg RD *n = Rt;
                for (; n->_s; )
                {
                    _r = n->c[0]->_s;
                    if (k <= _r) n = n->c[0];
                    else if (_r + 1 <= k && k <= _r + n->_w) break;
                    else k -= _r + n->_w, n = n->c[1];
                }
                return n->v;
            }
            
            Inline int Get_rank (const int &v)
            {
                rg int _r, cur = 0; rg RD *n = Rt;
                for (; n->_s; )
                {
                    _r = n->c[0]->_s;
                    if (n->v == v) break;
                    else if (n->v > v) n = n->c[0];
                    else cur += _r + n->_w, n = n->c[1];
                }
                return cur + _r + 1;
            }
            
            Inline int Find_Suffix (const int &v)
            {
                rg int _r = 0;
                for (RD *n = Rt; n->_s; )
                    if (n->v > v) _r = n->v, n = n->c[0];
                    else n = n->c[1];
                return _r;
            
            }
            
            Inline int Find_Prefix (const int &v)
            {
                rg int _r = 0;
                for (RD *n = Rt; n->_s; )
                    if (n->v < v) _r = n->v, n = n->c[1];
                    else n = n->c[0];
                return _r;
            }
    };
    Red_Black_Tree Rbt;
    void write_ (int n)
    { if (n > 9) write_ (n / 10); putchar (n % 10 + '0'); }
    inline void write (int n)
    {
        if (n < 0) putchar ('-'), n = -n;
        write_ (n); putchar ('
    ');
    }
    int Main ()
    {
        fread (buf, 1, BUF, stdin); int N; read (N);
        for (int type, x; N --; )
        {
            read (type); read (x);
               if (type == 1) Rbt.Insert (x);
            else if (type == 2) Rbt.Delete (x);
            else if (type == 3) write (Rbt.Get_rank (x));
            else if (type == 4) write (Rbt.Get_kth_number (x));
            else if (type == 5) write (Rbt.Find_Prefix (x));
            else write (Rbt.Find_Suffix (x));
        }
        return 0;
    }
    int ZlycerQan = Main(); int main(int argc, char *argv[]){;}
    #include <cstdio>
    #include <iostream>
     
    #define Max 100001
     
    #define Red true
    #define Black false
     
    const int BUF = 100000100;
    char Buf[BUF], *buf = Buf;
     
    #define Inline __attri
    bute__( ( optimize( "-O2" ) ) )
    Inline void read (int &now)
    {
        int temp = 0;
        for (now = 0; !isdigit (*buf); ++ buf)
            if (*buf == '-')
                temp = 1;
        for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf);
        if (temp)    
            now = -now;
    }
     
    struct R_D
    {
        int key, size, weigth;
        bool color;
        
        R_D *father, *child[2];
        
        Inline void Fill (const int &__key, const bool &__color, const int &z, register R_D *now)
        {
            this->key = __key;
            this->color = __color;
            this->size = this->weigth = z;
            
            this->father = this->child[0] = this->child[1] = now;
        }
        
        Inline void Up ()
        {
            this->size = this->child[0]->size + this->child[1]->size + this->weigth;
        }
        
        Inline void Down ()
        {
            for (R_D *now = this; now->size; now = now->father)
                now->size --;
        }
        
        Inline int Get_Pos (const int &now) const
        {
            return this->key == now ? -1 : now > this->key;
        } 
    };
     
     
    class Red_Black_Tree
    {
        
        private :
            
            int Top;
            
            R_D *Root, *null;
            R_D poor[Max], *Tail, *reuse[Max];
            
            
            Inline R_D *New (const int &key)
            {
                register R_D *now = null;
                if (!Top)
                    now = Tail ++;
                else
                    now = reuse[-- Top];
                now->Fill (key, Red, 1, null);
                return now;
            }
            
            Inline void Rotate (R_D *&now, const bool &pos)
            {
                register R_D *C = now->child[pos ^ 1];
                now->child[pos ^ 1] = C->child[pos];
                if (C->child[pos]->size)
                    C->child[pos]->father = now;
                C->father = now->father;
                if (!now->father->size)
                    Root = C;
                else 
                    now->father->child[now->father->child[0] != now] = C;
                C->child[pos] = now;
                now->father = C;
                C->size = now->size;
                now->Up ();
            }
            
            Inline void Insert_Fill (register R_D *&now)
            {
                for (; now->father->color; )
                {
                    R_D *Father = now->father, *Grand = Father->father;
                    bool pos = Father == Grand->child[0];
                    R_D *Uncle = Grand->child[pos];
                    if (Uncle->color)
                    {
                        Father->color = Uncle->color = Black;
                        Grand->color = Red;
                        now = Grand;
                    }
                    else if (now == Father->child[pos])
                        Rotate (now = Father, pos ^ 1);
                    else
                    {
                        Grand->color = Red;
                        Father->color = Black;
                        Rotate (Grand, pos);
                    }
                }
                Root->color = Black;
            }
            
            Inline R_D *Find (R_D *now, int key)
            {
                for (; now->size && now->key != key; now = now->child[now->key < key]);
                return now;
            }
            
            Inline void Delete_Fill (register R_D *&now)
            {
                for (; now != Root && now->color == Black; )
                {
                    register bool pos = now == now->father->child[0];
                    R_D *Father = now->father, *Uncle = Father->child[pos];
                    if (Uncle->color == Red)
                    {
                        Uncle->color = Black;
                        Father->color = Red;
                        Rotate (now->father, pos ^ 1);
                        Uncle = Father->child[pos];
                    }
                    else if (Uncle->child[0]->color == Black && Uncle->child[1]->color == Black)
                    {
                        Uncle->color = Red;
                        now = Father;
                    }
                    else
                    {
                        if (Uncle->child[pos]->color == Black)
                        {
                            Uncle->child[pos ^ 1]->color = Black;
                            Uncle->color = Red;
                            Rotate (Uncle, pos);
                            Uncle = Father->child[pos];
                        }
                        Uncle->color = Father->color;
                        Uncle->child[pos]->color = Father->color = Black;
                        Rotate (Father, pos ^ 1);
                        break;
                    }
                }
                now->color = Black;
            }
            
        public :
            
            Red_Black_Tree ()
            {
                Top = 0;
                Tail = &poor[Top];
                null = Tail ++;
                null->Fill (0, Black, 0, NULL);
                Root = null;
            }
            
            Inline void Insert (const int &key)
            {
                register R_D *now = Root, *Father = null;
                register int pos;
                for (; now->size; now = now->child[pos])
                {
                    now->size ++;
                    Father = now;
                    pos = now->Get_Pos (key);
                    if (pos == -1)
                    {
                        now->weigth ++;
                        return ;
                    }
                }
                now = New (key);
                if (Father->size)
                    Father->child[key > Father->key] = now;
                else
                    Root = now;
                now->father = Father;
                this->Insert_Fill (now); 
            }
            
            Inline void Delete (const int &key)
            {
                register R_D *res = Find (Root, key);
                if (!res->size)
                    return ;
                if (res->weigth > 1)
                {
                    res->weigth --;
                    res->Down ();
                    return ;
                }
                register R_D *Father = res, *now = null;
                
                if (res->child[0]->size && res->child[1]->size)
                    for (Father = res->child[1]; Father->child[0]->size; Father = Father->child[0]);
                
                now = Father->child[!Father->child[0]->size];
                now->father = Father->father;
                if (!Father->father->size)
                    Root = now;
                else
                    Father->father->child[Father->father->child[1] == Father] = now;
                
                if (res != Father)
                {
                    res->key = Father->key;
                    res->weigth = Father->weigth;
                }
                
                Father->father->Down ();
        
                for (R_D *Fuck = Father->father; Father->weigth > 1 && Fuck->size && Fuck != res; Fuck->size -= Father->weigth - 1, Fuck = Fuck->father);
        
                if (Father->color == Black)
                    Delete_Fill (now);
                
                reuse[Top ++] = Father;
            }
            
            Inline int Get_kth_number (register int k)
            {
                register int res;
                register R_D *now = Root;
                
                for (; now->size; )
                {
                    res = now->child[0]->size;
                    
                    if (k <= res)
                        now = now->child[0];
                    else if (res + 1 <= k && k <= res + now->weigth)
                        break;
                    else 
                    {
                        k -= res + now->weigth;
                        now = now->child[1];
                    }
                }
                return now->key;
            }
            
            Inline int Get_rank (const int &key)
            {
                register int res, cur = 0;
                register R_D *now = Root;
                
                for (; now->size; )
                {
                    res = now->child[0]->size;
                    if (now->key == key)
                        break;
                    else if (now->key > key)
                        now = now->child[0];
                    else
                    {
                        cur += res + now->weigth;
                        now = now->child[1];
                    }
                }
                
                return cur + res + 1;
            }
            
            Inline int Find_Suffix (const int &key)
            {
                register int res = 0;
                
                for (R_D *now = Root; now->size; )
                    if (now->key > key)
                    {
                        res = now->key;
                        now = now->child[0];
                    }
                    else 
                        now = now->child[1];
                
                return res;
            
            }
            
            Inline int Find_Prefix (const int &key)
            {
                register int res = 0;
                
                for (R_D *now = Root; now->size; )
                    if (now->key < key)
                    {
                        res = now->key;
                        now = now->child[1];
                    }
                    else
                        now = now->child[0];
                return res;
            }
    };
     
    Red_Black_Tree Rbt;
    
    void write_ (int now)
    {
        if (now > 9)
            write_ (now / 10);
        putchar (now % 10 + '0');
    }
    
    inline void write (int now)
    {
        if (now < 0) putchar ('-'), now = -now;
        write_ (now);
        putchar ('
    ');
    }
    
    
    int N;
     
    int Main ()
    {
        fread (buf, 1, BUF, stdin);
        read (N);
        
        for (int type, x; N --; )
        {
            read (type);
            read (x);
            
            switch (type)
            {
                case 1:
                    Rbt.Insert (x);
                    break;
                case 2:
                    Rbt.Delete (x);
                    break;
                case 3:
                    write (Rbt.Get_rank (x));
                    break;  
                case 4:
                    write (Rbt.Get_kth_number (x));
                    break;
                case 5:
                    write (Rbt.Find_Prefix (x));
                    break;
                case 6:
                    write (Rbt.Find_Suffix (x));
                    break;
            }
        }
        
        return 0;
    }
    int ZlycerQan = Main();
    int main(int argc, char *argv[]){;}
  • 相关阅读:
    纯JS.CSS编写的可拖拽并左右分栏的插件(复制代码就能用)
    jquery on()方法重复绑定解决方法
    在PHP语言中使用JSON和将json还原成数组
    Flex 布局教程:语法篇
    在线生成大全(这里真的什么都有)
    css3(border-radius)边框圆角详解
    css常用鼠标指针形状代码
    input 正则限制输入内容
    html中input标签的tabindex属性
    CSS gradient渐变之webkit核心浏览器下的使用
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7222393.html
Copyright © 2011-2022 走看看