zoukankan      html  css  js  c++  java
  • luogu P3369 普通平衡树

    luogu P3369

    主要是贴一个splay的模板:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace splay{
    
        #define ls(x) ch[x][0]
        #define rs(x) ch[x][1]
    
        const int N = 1000005;
        const int inf = 2e9;
        int ch[N][2],f[N],key[N],nums[N],sz[N];
        int rt, nodeCnt;
    
        void clearNode(int x){//删掉某一个节点
            sz[x]=ch[x][0]=ch[x][1]=f[x]=key[x]=nums[x]=0;
        }
    
        bool getDir(int x){//右儿子返回1,否则返回0
            return ch[f[x]][1]==x?1:0;
        }
    
        void update(int x){//这里是更新一下size
            if(x){
                sz[x]=nums[x];
                if(ls(x))sz[x]+=sz[ls(x)];
                if(rs(x))sz[x]+=sz[rs(x)];
            }
        }
    
        void rot(int x){
            int fa=f[x],gf=f[fa],ws=getDir(x),ws1=getDir(fa),w=ch[x][ws^1];
            ch[fa][ws]=w;f[w]=fa;
            ch[gf][ws1]=x;f[x]=gf;
            ch[x][ws^1]=fa;f[fa]=x;
            update(fa);update(x);
        }
    
        void Splay(int x, int goal=0){
            while(f[x]!=goal){
                int fa=f[x],gf=f[fa];
                if(gf!=goal){
                    if(getDir(x)==getDir(fa))rot(fa);//三点一线先旋转fa
                    else rot(x);
                }
                rot(x);
            }
    
            if(!goal)rt=x;
        }
    
        void Find(int v){//有v的情况出现v,否则出现一个前驱或者后继
            if(!rt)return;
    
            int curNode=rt;
            while(ch[curNode][v>key[curNode]]&&v!=key[curNode]){
                curNode=ch[curNode][v>key[curNode]];
            }
    
            Splay(curNode,0);
        }
    
        void Insert(int v){
            int curNode=rt,p=0;
            while(curNode&&key[curNode]!=v){
                p=curNode;
                curNode=ch[curNode][v>key[curNode]];
            }
    
            if(curNode){
                ++nums[curNode];
            }else{
                curNode=++nodeCnt;
                if(p)ch[p][v>key[p]]=curNode;
                f[curNode]=p;
                ch[curNode][0]=ch[curNode][1]=0;
                nums[curNode]=sz[curNode]=1;
                key[curNode]=v;
            }
            Splay(curNode,0);
        }
    
        int kth(int k){//第k大的节点,插入-inf和inf的情况下,传入k+1
            int curNode=rt;
            if(sz[curNode]<k)return 0;
            while(1){
                if(k<=sz[ls(curNode)]){
                    curNode=ls(curNode);
                }else if(k>sz[ls(curNode)]+nums[curNode]){
                    k-=sz[ls(curNode)]+nums[curNode];
                    curNode=rs(curNode);
                }else{
                    return curNode;
                }
            }
        }
    
        int Rank(int v){
            Find(v);
            if(key[rt]>=v)return sz[ls(rt)];
            else return sz[ls(rt)]+nums[rt];
        }
    
        int Next(int x, int op){//op=0,前驱,op=1后继,均为节点
            Find(x);
            if(key[rt]<x&&op==0)return rt;
            if(key[rt]>x&&op==1)return rt;
    
            int curNode=ch[rt][op];
            while(ch[curNode][op^1])curNode=ch[curNode][op^1];
    
            return curNode;
        }
    
        void del(int x){//前驱到根,后继到右子节点,中间剩个x
            int pre=Next(x,0);
            int nxt=Next(x,1);
            Splay(pre,0),Splay(nxt,pre);
    
            int node=ch[nxt][0];
            if(nums[node]>=2){
                --nums[node];
                Splay(node,0);
            }
            else{
                ch[nxt][0]=0;
            }
        }
    
    
        void init(){
            Insert(inf);
            Insert(-inf);
        }
    
    };
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    int main(){
    //    freopen("P3369_6.in","r",stdin);
    //    freopen("stdout.txt","w",stdout);
        int q=read();
        splay::init();
        while(q--){
            int opt=read();
            if(opt==1){
                splay::Insert(read());
            }else if(opt==2){
                splay::del(read());
            }else if(opt==3){
                cout<<splay::Rank(read())<<endl;
            }else if(opt==4){
                cout<<splay::key[splay::kth(read()+1)]<<endl;
            }else if(opt==5){
                cout<<splay::key[splay::Next(read(),0)]<<endl;
            }else{
                cout<<splay::key[splay::Next(read(),1)]<<endl;
            }
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    「BZOJ 1000」A+B Problem
    「HNOI 2008」越狱
    蓝桥杯 拼音字母
    蓝桥杯 抽签
    蓝桥杯 快速排序
    [蓝桥杯] 最大比例
    [蓝桥杯] 交换瓶子
    [蓝桥杯] 四平方和
    [蓝桥杯] 剪邮票
    [蓝桥杯] 方格填数
  • 原文地址:https://www.cnblogs.com/JohnRan/p/12885309.html
Copyright © 2011-2022 走看看