zoukankan      html  css  js  c++  java
  • P3369 【模板】普通平衡树

    纯板子。。。。

    题意:

    1. 插入 xx 数
    2. 删除 xx 数(若有多个相同的数,因只删除一个)
    3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
    4. 查询排名为 xx 的数
    5.  xx 的前驱(前驱定义为小于 xx ,且最大的数)
    6.  xx 的后继(后继定义为大于 xx ,且最小的数)

    然后。。。

    然后就没有然后了。。。。

    注意rotate。。。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    #define olinr return 
    #define love_nmr 0
    #define INF 0x7ffffffa
    #define mod 123123
    int n;
    int cnt;
    int root;
    int siz[mod];
    int dat[mod];
    int fat[mod];
    int num[mod];
    int son[mod][2];
    inline int read()
    {
        int f=1,x=0;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        olinr x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    
    
    /* ------------------------olinr love nmr--------------------------------*/
    
    
    inline void update(int x)
    {
        siz[x]=siz[son[x][0]]+siz[son[x][1]]+num[x];
    }
    inline void rotate(int x,int &o)
    {
        int y=fat[x];
        int z=fat[y];
        bool xx=son[y][1]==x;
        bool yy=xx^1;
        if(y==o)
            o=x;
        else
            son[z][son[z][1]==y]=x;
        fat[x]=z;
        fat[y]=x;
        fat[son[x][yy]]=y;
        son[y][xx]=son[x][yy];
        son[x][yy]=y;
        update(y);
        update(x);
        olinr;
    }
    inline void splay(int x,int &o)
    {
        while(x!=o)
        {
            int y=fat[x];
            int z=fat[y];
            if(y!=o)
            {
                if((son[y][0]==x)^(son[z][0]==y))
                    rotate(x,o);
                else
                    rotate(y,o);
            }    
            rotate(x,o);
        }
    }
    inline int x_rank_n(int x)
    {
        int now=root;
        int rank=0;
        while(5201314+love_nmr)
        {
            if(x<dat[now])
                now=son[now][0];
            else
            {
                rank+=siz[son[now][0]];
                if(x==dat[now])
                {
                    splay(now,root);
                    olinr rank+1;
                }
                rank+=num[now];
                now=son[now][1];
            }
        }
    }
    inline int n_rank_x(int x)
    {
        int now=root;
        while(5201314+love_nmr)
        {
            if(siz[son[now][0]]>=x)
                now=son[now][0];
            else
            {
                if(num[now]+siz[son[now][0]]>=x)
                    olinr dat[now];
                x-=(num[now]+siz[son[now][0]]);
                now=son[now][1];
            }
        }
    }
    inline int pre(int x)
    {
        x_rank_n(x);
        int now=son[root][0];
        while(son[now][1])
            now=son[now][1];
        olinr now;
    }
    inline int nxt(int x)
    {
        x_rank_n(x);
        int now=son[root][1];
        while(son[now][0])
            now=son[now][0];
        olinr now;
    }
    inline int del(int x)
    {
        int l=pre(x);
        int r=nxt(x);
        splay(l,root);
        splay(r,son[root][1]);
        int now=son[son[root][1]][0];
        siz[now]--;
        num[now]--;
        if(!num[now])
        {
            son[fat[now]][0]=0;
            fat[now]=0;
        }
        splay(son[root][1],root);
    }
    inline void insert(int x)
    {
        if(!root)
        {
            root=++cnt;
            siz[root]=1;
            dat[root]=x;
            num[root]=1;
            olinr;
        }
        int fa=0;
        int now=root;
        while(5201314+love_nmr)
        {
            if(dat[now]==x)
            {
                num[now]++;
                siz[now]++;
                splay(now,root);
                olinr;
            }
            fa=now;
            now=son[now][x>dat[now]];
            if(!now)
            {
                now=++cnt;
                fat[now]=fa;
                son[fa][x>dat[fa]]=now;
                num[now]++;
                siz[now]++;
                dat[now]=x;
                splay(now,root);
                olinr;
            }
        }
    }
    int main()
    {
        n=read();
        int flag,x;
        insert(INF);
        insert(-INF);
        for(int i=1;i<=n;i++)
        {
            flag=read();
            x=read();
            if(flag==1) insert(x);
            if(flag==2) del(x);
            if(flag==3){put(x_rank_n(x)-1);putchar('
    ');}
            if(flag==4){put(n_rank_x(x+1));putchar('
    ');}
            if(flag==5){insert(x);put(dat[pre(x)]);putchar('
    ');del(x);}
            if(flag==6){insert(x);put(dat[nxt(x)]);putchar('
    ');del(x);}
        }
        olinr love_nmr;
    }

     注释QAQ

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    using namespace std;
    #define R register
    #define IL inline
    #define INF 2147483640
    #define mod 125125
    #define II int
    II root;            //根的编号                                 
    II n;                 //n个操作 
    II cnt;                //编号 
    II fa[mod];            //fa[i]代表i的父亲 
    II son[mod][2];        //son[i][0]代表i的左儿子,son[i][1]代表i的右儿子 
    II data[mod];        //data[i]代表树上编号为i的点的值 
    II size[mod];        //size[i]表示以i为根的子树的sum的和 (大小) (包括自己) 
    II sum[mod];        //sum[i]表示数字i的个数 
    IL II read()        //快读(有负数) 
    {
        R II x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    IL void update(R II x)  //更新x 
    {
        size[x]=size[son[x][0]]+size[son[x][1]]+sum[x];
        //当前点的size == 左儿子的size + 右儿子的size + 当前点的个数 
    }
    IL void rotate(R II x,R II &o)    //旋转 
    {
        R II y=fa[x];                //y为x的父亲 
        R II z=fa[y];                //z为y的父亲,z为x的爷爷 
        R bool xx=(son[y][1]==x);    //xx表示y的右儿子是否为x 
        R bool yy=xx^1;                //yy表示y的左儿子是否为x 
        if(y==o)                     //x的父亲y是旋转的目标点 
            o=x;                    //目标点变为x 
        else                        //x的父亲y不是旋转的目标点 
            son[z][son    [z][1]==y]=x;    //如果z的右儿子是y,那么现在z的右儿子是x;如果z的右儿子不是y,那么现在z的左儿子是x 
        fa[x]=z;                     //x的父亲是z 
        fa[y]=x;                    //y的父亲是x(x转了上去) 
        fa[son[x][yy]]=y;            //如果原来y的左儿子是x,那么现在x的右儿子是y;如果原来y的右儿子是x,那么现在x的左儿子是y 
        son[y][xx]=son[x][yy];         //原来x的(右||左)儿子变成了先在y的(左||右)儿子 
        son[x][yy]=y;                //如果原来y的(左||右)儿子是x,那么现在x的(右||左)儿子是y 
        update(y);                    //维护y 
        update(x);                    //维护x 
    }
    IL void splay(R II x,R II &o)
    {
        while(x!=o)                                    //只要为转到目标节点 
        {                            
            R II y=fa[x];                            //y是x的父亲 
            R II z=fa[y];                            //z是y的父亲,x的爷爷 
            if(y!=o)                                //如果y不是目标节点 
            {
                if((son[y][0]==x)^(son[z][0]==y))    //如果xyz不在一条直链上 
                    rotate(x,o);                    //x朝o的方向转 
                else                                //在一条直链上 
                    rotate(y,o);                    //转y 
            }                                            
            rotate(x,o);                            //转x 
        }
    }
    IL void insert(R II x)        
    {
        if(!root)                            //是根 
        {                                    //初始化 
            root=++cnt;
            data[root]=x;
            size[root]=1;
            sum[root]=1;
            return;
        }
        R II now=root;                        //从根开始找合适位置 
        R II fat=0;                            //now的father                    
        while(5201314)         
        {
            if(data[now]==x)                 //树中已有该元素 
            {
                sum[now]++;                    //累计数量 
                splay(now,root);            //
                return;
            }
            fat=now;
            now=son[now][data[now]<x];        //now往孩子上跳 
            if(!now)                        //跳到了叶子的孩子(还没有) 
            {
                now=++cnt;                    //初始化 
                fa[now]=fat;
                son[fat][data[fat]<x]=now;
                size[now]++;
                sum[now]++;
                data[now]=x;
                splay(now,root);
                return;
            }
        }
    }
    IL II x_rank_n(R II x)                 //找树中的数x的排名 
    {
        R II rank=0;                     
        R II now=root;                    //从根往下找 
        while(5201314)
        {
            if(x<data[now])                //小于当前点往左跳 
                now=son[now][0];
            else                    
            {
                rank+=size[son[now][0]];//排名加上左子树大小(x一定比左子树所有值都大,不然就会往左跳) 
                if(x==data[now])        //找到了x 
                {
                    splay(now,root);    //转上去 
                    return rank+1;        //x的位置 
                }
                rank+=sum[now];            //往右跳说明它比前面所有数都大,所以要累计前面数的个数 
                now=son[now][1];        //累计完后在往后跳 
            }
        }
    }
    IL II rank_n_x(R II x)                
    {
        R II rank=0;
        R II now=root;
        while(5201314)
        {
            if(size[son[now][0]]>=x)                //目标在左子树 
                now=son[now][0];                    //往左跳 
            else
            {
                if(sum[now]+size[son[now][0]]>=x)     //now就是x的位置 
                    return data[now];
                x-=(sum[now]+size[son[now][0]]);    //x减左边个数 
                now=son[now][1];                    //再向右跳 
            }
        }
    }
    IL II pre(R II x)
    {
        x_rank_n(x);
        R II now=son[root][0];
        while(son[now][1])
            now=son[now][1];
        return now;
    }
    IL II nxt(R II x)
    {
        x_rank_n(x);
        R II now=son[root][1];
        while(son[now][0])
            now=son[now][0];
        return now;
    }
    IL void del(R II x)
    {
        R II l=pre(x);
        R II r=nxt(x);
        splay(l,root);
        splay(r,son[root][1]);
        R II now=son[son[root][1]][0];
        sum[now]--;
        size[now]--;
        if(!sum[now])
        {
            son[fa[now]][0]=0;
            fa[now]=0;
        }
        splay(son[root][1],root);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        n=read();
        insert(-INF);
        insert(INF);
        for(R II i=1;i<=n;i++)
        {
            R II x=read();
            R II y=read();
            if(x==1) insert(y);
            if(x==2) del(y);
            if(x==3) printf("%d
    ",x_rank_n(y)-1);
            if(x==4) printf("%d
    ",rank_n_x(y+1));
            if(x==5) insert(y),printf("%d
    ",data[pre(y)]),del(y);
            if(x==6) insert(y),printf("%d
    ",data[nxt(y)]),del(y);
        }
        return 0;
    }
  • 相关阅读:
    ELF文件格式解析
    了解ELF文件类型
    汇编程序-简介
    汇编指令入门级整理
    双系统: Windows10时间快和Ubuntu时间差问题
    iDRAC on DELL Server
    ubuntu WIFI 连接不稳定(wifi无法连接问题)
    删除字符串中的空格(空字符)
    VBS 基础知识
    VBS 操作Excel的常用方法
  • 原文地址:https://www.cnblogs.com/olinr/p/9448435.html
Copyright © 2011-2022 走看看