zoukankan      html  css  js  c++  java
  • BZOJ3224:普通平衡树(splay练习)

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    Input

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    Output

    对于操作3,4,5,6每行输出一个数,表示对应答案

    Sample Input10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598

    Sample Output106465 84185 492737 Hint

    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-2e9,2e9]
     
    不多说了,模板练习。
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;    
    struct Splay{
        int ch[maxn][2],fa[maxn],num[maxn],sz[maxn],key[maxn],rt,cnt;
        int get(int x) { return ch[fa[x]][1]==x;}
        Splay(){ rt=cnt=0; }
        void update(int Now)
        {
            if(!Now) return ;
            sz[Now]=num[Now];
            if(ch[Now][0]) sz[Now]+=sz[ch[Now][0]];
            if(ch[Now][1]) sz[Now]+=sz[ch[Now][1]];
        }
        void rotate(int x)
        {
            int old=fa[x],fold=fa[old],opt=(ch[old][1]==x);
            fa[ch[x][opt^1]]=old; ch[old][opt]=ch[x][opt^1];
            ch[x][opt^1]=old; fa[old]=x; fa[x]=fold;
            if(fold) ch[fold][ch[fold][1]==old]=x;
            else rt=x;
            update(old); update(x);
        }
        void splay(int x,int y)
        {
            for(int f;(f=fa[x])!=y;rotate(x)){
                if(fa[f]!=y) 
                   rotate(get(x)==get(f)?f:x);
            }
            if(!y) rt=x;
        }
        void insert(int x)
        {
            if(!rt){
               rt=++cnt; key[cnt]=x; sz[cnt]=num[cnt]=1;  return ;
            }
            int Now=rt,f=0;
            while(true){
                if(key[Now]==x){
                    num[Now]++; update(Now); update(f); splay(Now,0); return;
                }
                f=Now; Now=ch[Now][key[Now]<x];
                if(!Now) {
                    fa[++cnt]=f; ch[f][key[f]<x]=cnt; num[cnt]=sz[cnt]=1; 
                    key[cnt]=x; update(f);  splay(cnt,0); return ;
                }
            }
        }  
        void del(int x)
        {
             int whatever=find(x);  
             if(num[rt]>1){num[rt]--; update(rt); return;}  
             if(!ch[rt][0]&&!ch[rt][1]) { rt=0; return;}  
             if(!ch[rt][0]){  
                  int oldroot=rt; rt=ch[rt][1]; fa[rt]=0;  return;  
             }  
             else if (!ch[rt][1]){  
                 int oldroot=rt; rt=ch[rt][0]; fa[rt]=0;  return;  
             }  
             int leftbig=pre(),oldroot=rt;  
             splay(leftbig,0);  
             ch[rt][1]=ch[oldroot][1];  
             fa[ch[oldroot][1]]=rt;  
             update(rt);     
        }
        int find(int x)
        {
            int Now=rt,res=0;
            while(true){
                 if(x<key[Now]) Now=ch[Now][0];
                 else {
                     res+=ch[Now][0]?sz[ch[Now][0]]:0;
                     if(key[Now]==x) {
                          splay(Now,0);return res+1;
                     }
                     res+=num[Now]; Now=ch[Now][1];
                 }
            }
        }
        int findx(int x)
        {
            int Now=rt;
            while(true){
                if(ch[Now][0]&&sz[ch[Now][0]]>=x) Now=ch[Now][0];
                else {
                    if(ch[Now][0]) x-=sz[ch[Now][0]];
                    if(num[Now]>=x) return key[Now];
                    x-=num[Now];
                    Now=ch[Now][1];
                }
            }
        }
        int pre()
        {
            int Now=ch[rt][0];    
            while(ch[Now][1]) Now=ch[Now][1];
            return Now;
        }
        int nxt()
        {
            int Now=ch[rt][1];
            while(ch[Now][0]) Now=ch[Now][0];
            return Now;
        }
    }S;
    int main()
    {
        int N,opt,x;
        scanf("%d",&N);
        while(N--){
            scanf("%d%d",&opt,&x);
            switch(opt){
                case 1: S.insert(x); break;
                case 2: S.del(x); break;
                case 3: printf("%d
    ",S.find(x)); break;
                case 4: printf("%d
    ",S.findx(x)); break;
                case 5: S.insert(x); printf("%d
    ",S.key[S.pre()]); S.del(x);break;
                case 6: S.insert(x); printf("%d
    ",S.key[S.nxt()]); S.del(x);break;
            }
        }
        return 0;
    }
  • 相关阅读:
    git安装
    git
    运维项目维护个人总结经验
    redis基本命令
    mysql基础常用命令
    进入Linux单用户模式
    Nginx查看并发链接数
    linux编写脚本检测本机链接指定IP段是否畅通
    集体干死java 在启动.sh
    系统优化小脚本
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8622537.html
Copyright © 2011-2022 走看看