Live2d Test Env

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\n",S.find(x)); break;
            case 4: printf("%d\n",S.findx(x)); break;
            case 5: S.insert(x); printf("%d\n",S.key[S.pre()]); S.del(x);break;
            case 6: S.insert(x); printf("%d\n",S.key[S.nxt()]); S.del(x);break;
        }
    }
    return 0;
}

 

posted @ 2018-03-22 11:31  nimphy  阅读(241)  评论(0编辑  收藏  举报