BZOJ 3224 普通平衡树

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 16841  Solved: 7319
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
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 Input

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

Sample Output

106465
84185
492737

HINT

 

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]

 

Source

很裸的平衡树Treep,Splay都能写
#include <bits/stdc++.h>
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1;  char ch=getc();
while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
return x*f;
}
void put(int x){
if(x==0){
putchar('0');
putchar('\n');
return;
}
if(x<0){
putchar('-');
x=-x;
}
int num=0;char ch[16];
while(x) ch[++num]=x%10+'0',x/=10;
while(num) putchar(ch[num--]);
putchar('\n');
}
const int MAXN=1e6+10;
namespace zhangenming{
    struct node{
        int weight,sum,have,v;//weight表示节点的含有个数,sum表示所有子节点的和,have表示优先级,v表示节点的值
        int leftt,rightt;
    }T[MAXN];
    int n,tol=0,ans=0,root=0;
    inline void update(int root){
        T[root].sum=T[T[root].leftt].sum+T[T[root].rightt].sum+T[root].weight;
    }
    inline void left_rote(int &now){
        int tmp=T[now].rightt;
        T[tmp].sum=T[now].sum;
        T[now].rightt=T[tmp].leftt;
        T[tmp].leftt=now;
        update(now);now=tmp;
    }
    inline void right_rote(int &now){
        int tmp=T[now].leftt;
        T[tmp].sum=T[now].sum;
        T[now].leftt=T[tmp].rightt;
        T[tmp].rightt=now;
        update(now);now=tmp;
    }
    inline void insert(int x,int &root){
        if(root==0){
            tol++;root=tol;T[root].v=x;
            T[root].weight=T[root].sum=1;
            T[root].have=rand();return ;
        }
        T[root].sum++;
        if(T[root].v==x) {T[root].weight++;}
        else{
            if(x<T[root].v){
                insert(x,T[root].leftt);
                if(T[T[root].leftt].have>T[root].have) right_rote(root);
            }
            else{
                insert(x,T[root].rightt);
                if(T[T[root].rightt].have>T[root].have) left_rote(root);
            }
        }
    }
    inline void delte(int x,int &root){
        if(root==0) return ;
        if(x==T[root].v){
            if(T[root].weight>1){
                T[root].weight--;T[root].sum--;return ;
            }
            if(T[root].leftt*T[root].rightt==0){
                root=T[root].leftt+T[root].rightt;
            }
            else{
                if(T[T[root].leftt].have<T[T[root].rightt].have){
                    right_rote(root);delte(x,root);
                }
                else{
                    left_rote(root);delte(x,root);
                }
            }
        }
        else{
            if(T[root].v>x) {T[root].sum--;delte(x,T[root].leftt);}
            else {T[root].sum--;delte(x,T[root].rightt);}
        }
    }
    inline int getrank(int x,int root){
        if(root==0) return 0;
        if(T[root].v>x) return getrank(x,T[root].leftt);
        else{
            if(T[root].v<x) return T[T[root].leftt].sum+T[root].weight+getrank(x,T[root].rightt);
            else return T[T[root].leftt].sum+1;
        } 
    }
    inline int getnum(int x,int root){
        if(root==0) return 0;
            if(x>T[root].weight+T[T[root].leftt].sum){
                return getnum(x-T[root].weight-T[T[root].leftt].sum,T[root].rightt);
            }
        else{
            if(x>T[T[root].leftt].sum){
                return T[root].v;
            }
            else{
                return getnum(x,T[root].leftt);
            }
        }
    }
    inline void getpre(int x,int root){
        if(root==0) return;
        if(T[root].v<x){
            ans=T[root].v;
            getpre(x,T[root].rightt);
        }
        else getpre(x,T[root].leftt);
    }
    inline void getnext(int x,int root){
        if(root==0) return;
        if(T[root].v>x){
            ans=T[root].v;
            getnext(x,T[root].leftt);
        }
        else getnext(x,T[root].rightt);
    }
    void init(){
        n=read();
        for(int i=1;i<=n;i++){
            int id=read();
            int xx=read();
            if(id==1) insert(xx,root);
            if(id==2) delte(xx,root);
            if(id==3) put(getrank(xx,root));
            if(id==4) put(getnum(xx,root));
            if(id==5) {getpre(xx,root);put(ans);}
            if(id==6) {getnext(xx,root);put(ans);}
        }
    }
}
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    using namespace zhangenming;
    init();
    return 0;
}

 

 

posted @ 2017-11-22 20:23  zhangenming  阅读(167)  评论(0编辑  收藏  举报