BZOJ_P3224&Tyvj_P1728&Codevs_P4543 普通平衡树

84 篇文章 0 订阅
9 篇文章 0 订阅

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6120 Solved: 2516
[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.每个数的数据范围:[-1e7,1e7]

Source
平衡树.

#include<cstdio>
#include<climits>
#include<cstdlib>
#include<iostream>
using namespace std;
#define INF INT_MAX/3*2
struct SplayTree{
    struct Node{
        Node *ch[2];
        int r,v,s,size;
        Node(int v,Node* nl):v(v){size=s=1;r=rand();ch[0]=ch[1]=nl;}
        void maintain(){size=ch[0]->size+s+ch[1]->size;}
    }*root,*null;

    SplayTree(){
        null=new Node(0,0);null->r=INT_MAX;null->size=null->s=0;
        null->ch[0]=null->ch[1]=null;root=null;
    }
    void rotate(Node* &o,int d){
        Node *k=o->ch[d];o->ch[d]=k->ch[d^1];k->ch[d^1]=o;
        o->maintain();k->maintain();o=k;
    }   
    void insert(Node* &o,int x){
        if(o==null){o=new Node(x,null);return;}
        if(o->v==x){o->s++,o->size++;return;}
        insert(o->ch[x>o->v],x);
        if(o->ch[x>o->v]->r<o->r) rotate(o,x>o->v);
        else o->maintain();
    }
    void remove(Node* &o,int x){
        if(o->v==x){
            if(o->s>1){o->s--;o->size--;return;}
            int d=o->ch[0]->r>o->ch[1]->r;
            if(o->ch[d]==null){delete o;o=null;return;}
            rotate(o,d);remove(o->ch[d^1],x);
        }
        else remove(o->ch[x>o->v],x);
        o->maintain();
    }
    int kth(Node *o,int x){
        int d=o->ch[0]->size;
        if(x<=d) return kth(o->ch[0],x);
        else if(x>d+o->s) return kth(o->ch[1],x-d-o->s);
        return o->v;
    }
    int rank(Node *o,int x){
        int d=o->ch[0]->size;
        if(x<o->v) return rank(o->ch[0],x);
        else if(x>o->v) return rank(o->ch[1],x)+d+o->s;
        return d;
    }
    int prev(Node *o,int x){
        if(o==null) return -INF;
        if(x<=o->v) return prev(o->ch[0],x);
        return max(o->v,prev(o->ch[1],x));
    }
    int next(Node* o,int x){
        if(o==null) return INF;
        if(x>=o->v) return next(o->ch[1],x);
        return min(o->v,next(o->ch[0],x));
    }

}T;
int main(){
    srand('B'+'e'+'i'+'Y'+'u');
    int n,opt,x;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&opt,&x);
        switch(opt){
            case 1:
                T.insert(T.root,x);break;
            case 2:
                T.remove(T.root,x);break;
            case 3:
                printf("%d\n",T.rank(T.root,x)+1);break;
            case 4:
                printf("%d\n",T.kth(T.root,x));break;
            case 5:
                printf("%d\n",T.prev(T.root,x));break;
            case 6: 
                printf("%d\n",T.next(T.root,x));break;
        } 
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值