平衡树模板

Splay

#define lch ch[0]
#define rch ch[1]
class Splay{
    private:
        struct Node{
            int val,cnt,sz;
            Node *fa,*ch[2];
            inline void pushup(){
                sz=cnt;
                if(lch) sz+=lch->sz;
                if(rch) sz+=rch->sz;
            }
            inline bool checkson(){
                return this==fa->rch;
            }
            Node(){}
            Node(int x){
                val=x;cnt=1;sz=1;
                fa=lch=rch=nullptr;
            }
            Node(int x,Node *ptr){
                val=x;cnt=1;sz=1;
                fa=ptr;
                lch=rch=nullptr;
            }
        };
        Node *rt;
        inline void rotate(Node *x){
            assert(x);
            Node *y=x->fa,*z=y->fa;
            int dir=!x->checkson();
            y->ch[!dir]=x->ch[dir];
            if(x->ch[dir]) x->ch[dir]->fa=y;
            x->ch[dir]=y;

            y->fa=x;
            x->fa=z;
            if(z) z->ch[y==z->rch]=x;

            y->pushup();
            x->pushup(); 
        }
        inline void splay(Node *cur){
            assert(cur);
            if(cur==rt) return;
            Node *curfa;
            while(cur->fa){
                curfa=cur->fa;
                if(curfa->fa) rotate(cur->checkson()==curfa->checkson()?curfa:cur);
                rotate(cur);
            }
            rt=cur;
        }
        inline Node* getrtpre(){
            Node *cur=rt->lch;
            if(!cur) return cur;
            while(cur->rch) cur=cur->rch;
            splay(cur);
            return cur;
        }
        inline Node* getrtnxt(){
            Node *cur=rt->rch;
            if(!cur) return cur;
            while(cur->lch) cur=cur->lch;
            splay(cur);
            return cur;
        }
    public:
        inline void insert(int val){
            if(!rt){
                rt=new Node(val);
                return;
            }
            Node *cur=rt,*curfa=nullptr;
            while(true){
                assert(cur);
                if(cur->val==val){
                    cur->cnt++;
                    cur->pushup();
                    if(curfa) curfa->pushup();
                    splay(cur);
                    break;
                }
                curfa=cur;
                cur=cur->ch[cur->val<val];
                if(!cur){
                    curfa->ch[curfa->val<val]=new Node(val,curfa);
                    curfa->pushup();
                    splay(curfa->ch[curfa->val<val]);
                    break;
                }
            }
        }
        inline int query_val_rk(int val){
            int res=0;
            Node *cur=rt;
            while(true){
                assert(cur);
                if(val < cur->val){
                    if(cur->lch) cur=cur->lch;
                    else return res+1;
                }
                else{
                    res+=cur->lch?cur->lch->sz:0;
                    if(val==cur->val){
                        splay(cur);
                        return res+1;
                    }
                    else{
                        res+=cur->cnt;
                        if(cur->rch) cur=cur->rch;
                        else return res+1;
                    }
                }
            }
        }
        inline int query_kth_val(int k){
            Node *cur=rt;
            while(true){
                assert(cur);
                if(cur->lch && k<=cur->lch->sz) cur=cur->lch;
                else{
                    k-=cur->lch?cur->lch->sz:0;
                    if(k<=cur->cnt){
                        splay(cur);
                        return cur->val;
                    }
                    else{
                        k-=cur->cnt;
                        cur=cur->rch;
                    }
                }
            }
        }
        inline void del(int val){
            query_val_rk(val);//splay [val] to root
            if(rt->cnt>1){
                rt->cnt--;
                rt->pushup();
                return;
            }
            //now [val] is the root, we need to del the root and merge its left and right sons
            if((!rt->lch) && (!rt->rch)){
                delete rt;
                rt=nullptr;
            }
            else if(!rt->lch){
                Node *tmp=rt;
                rt=rt->rch;
                rt->fa=nullptr;
                delete tmp;
            }
            else if(!rt->rch){
                Node *tmp=rt;
                rt=rt->lch;
                rt->fa=nullptr;
                delete tmp;
            }
            else{
                Node *oldrt=rt,*ptr=getrtpre();
                oldrt->rch->fa=ptr;
                ptr->rch=oldrt->rch;
                delete oldrt;
                rt->pushup();
            }
        }
        inline int query_pre(int val){
            Node *ptr;
            int res;
            insert(val);
            ptr=getrtpre();
            res=ptr?ptr->val:-0x3f3f3f3f;
            del(val);
            return res;
        }
        inline int query_nxt(int val){
            Node *ptr;
            int res;
            insert(val);
            ptr=getrtnxt();
            res=ptr?ptr->val:-0x3f3f3f3f;
            del(val);
            return res;
        }
};

Treap

#define lch ch[0]
#define rch ch[1]
mt19937 mt_rand(time(NULL));
class Treap{
    private:
        struct Node{
            Node *ch[2];
            int val,pri,cnt,sz;
            Node(int v):val(v),cnt(1),sz(1){
                lch=rch=nullptr;
                pri=mt_rand();
            }
            void pushup(){
                sz=cnt;
                if(lch) sz+=ch[0]->sz;
                if(rch) sz+=ch[1]->sz;
            }
        };
        int qpre,qsuf;
        inline void rotate(Node *&cur,int dir){
            assert(cur);
            Node *tmp=cur->ch[!dir];
            cur->ch[!dir]=tmp->ch[dir];
            tmp->ch[dir]=cur;
            cur->pushup();
            tmp->pushup();
            cur=tmp;
        }
    public:
        Node *root=nullptr;
        void print(Node *x) {
            if (!x) return;
            cout<<x->val<<':'<<'[';
            print(x->lch);
            cout<<'|';
            print(x->rch);
            cout<<']';
        }
        void insert(Node *&cur,int val){
            if(cur==nullptr){
                cur=new Node(val);
                return;
            }
            else if(val==cur->val){
                cur->cnt++;
                cur->sz++;
            }
            else if(val<cur->val){
                insert(cur->lch,val);
                if(cur->lch->pri < cur->pri) rotate(cur,1);
                cur->pushup();
            }
            else{
                insert(cur->rch,val);
                if(cur->rch->pri < cur->pri) rotate(cur,0);
                cur->pushup();
            }
        }
        void del(Node *&cur,int val){
            assert(cur);
            if(val>cur->val){
                del(cur->rch,val);
                cur->pushup();
            }
            else if(val<cur->val){
                del(cur->lch,val);
                cur->pushup();
            }
            else{
                if(cur->cnt>1){
                    cur->cnt--;
                    cur->sz--;
                }
                else{
                    int state=(int)(cur->lch!=nullptr)+(int)(cur->rch!=nullptr)*2;
                    Node *tmp=cur;
                    switch(state){
                        case 0:{
                            delete cur;
                            cur=nullptr;
                            break;
                        }
                        case 1:{
                            cur=tmp->lch;
                            delete tmp;
                            break;
                        }
                        case 2:{
                            cur=tmp->rch;
                            delete tmp;
                            break;
                        }
                        case 3:{
                            if(cur->lch->pri < cur->rch->pri){
                                rotate(cur,1);
                                del(cur->rch,val);
                            }
                            else{
                                rotate(cur,0);
                                del(cur->lch,val);
                            }
                            cur->pushup();
                            break;
                        }
                    }
                }
            }
        }
        int query_rank(Node *cur,int val){
            assert(cur);
            int lftsz=cur->lch==nullptr ? 0 : cur->lch->sz;
            if(val==cur->val) return lftsz+1;
            else if(val<cur->val) return query_rank(cur->lch,val);
            else return lftsz+cur->cnt+query_rank(cur->rch,val);
        }
        int query_val(Node *cur,int rk){
            assert(cur);
            int lftsz=cur->lch==nullptr ? 0 : cur->lch->sz;
            if(rk<=lftsz) return query_val(cur->lch,rk);
            else if(rk<=lftsz+cur->cnt) return cur->val;
            else return query_val(cur->rch,rk-lftsz-cur->cnt);
        }
        int query_pre(Node *cur,int val){
            assert(cur);
            if(val<=cur->val){
                if(cur->lch) return query_pre(cur->lch,val);
            }
            else{
                qpre=cur->val;
                if(cur->rch) query_pre(cur->rch,val);
                return qpre;
            }
            return -0x3f3f3f3f;
        }
        int query_suf(Node *cur,int val){
            assert(cur);
            if(val>=cur->val){
                if(cur->rch) return query_suf(cur->rch,val);
            }
            else{
                qsuf=cur->val;
                if(cur->lch) query_suf(cur->lch,val);
                return qsuf;
            }
            return -0x3f3f3f3f;
        }
};

Fhq-Treap

#define lch t[pos].ls
#define rch t[pos].rs
mt19937 mt_rand(time(NULL));
class FhqTreap{
    private:
        int cnt;
        inline int newnode(int v){
            t[++cnt].sz=1;
            t[cnt].val=v;
            t[cnt].pri=mt_rand();
            t[cnt].ls=t[cnt].rs=0;
            return cnt;
        }
        inline void pushup(int pos){
            t[pos].sz=t[lch].sz+t[rch].sz+1;//tag
        }
        void split(int pos,int x,int &L,int &R){
            if(pos==0){
                L=R=0;
                return;
            }
            if(x>=t[pos].val){
                L=pos;
                split(rch,x,rch,R);
            }
            else{
                R=pos;
                split(lch,x,L,lch);
            }
            pushup(pos);
        }
        int merge(int L,int R){
            if(L==0||R==0) return L+R;
            if(t[L].pri<t[R].pri){
                t[L].rs=merge(t[L].rs,R);
                pushup(L);
                return L;
            }
            else{
                t[R].ls=merge(L,t[R].ls);
                pushup(R);
                return R;
            }
        }
    public:
        struct Node{
            int ls,rs,val,pri,sz;
        }t[MAXN];
        int root;
        inline void insert(int x){//tag
            int L,R;
            split(root,x,L,R);
            root=merge(merge(L,newnode(x)),R);
        }
        inline void del(int x){
            int L,R,P;
            split(root,x,L,R);
            split(L,x-1,L,P);
            root=merge(merge(L,merge(t[P].ls,t[P].rs)),R);
        }
        inline int query_rank(int x){
            int L,R,res;
            split(root,x-1,L,R);
            res=t[L].sz+1;
            merge(L,R);
            return res;
        }
        int query_kth(int pos,int k){
            if(k==t[lch].sz+1) return pos;
            else if(k<t[lch].sz+1) return query_kth(lch,k);
            else return query_kth(rch,k-t[lch].sz-1);//tag
        }
        inline int query_pre(int x){
            int L,R,res;
            split(root,x-1,L,R);
            res=t[query_kth(L,t[L].sz)].val;
            merge(L,R);
            return res;
        }
        inline int query_suf(int x){
            int L,R,res;
            split(root,x,L,R);
            res=t[query_kth(R,1)].val;
            merge(L,R);
            return res;
        }
};
posted @ 2023-09-27 19:15  MessageBoxA  阅读(8)  评论(0编辑  收藏  举报