【模板】普通平衡树 Treap

题目描述

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

输入输出格式

输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 )

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

输入输出样例

输入样例#1:
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1:
106465
84185
492737
说明

时空限制:1000ms,128M

1.n的数据范围: n≤100000
2.每个数的数据范围: [-{10}^7, {10}^7]

卡了我一星期的数据结构,今天终于A了一题,感觉可以欢呼一下。。。
大概有以下几个错误:
1.忘记判断 o == NULL
2.cmp搞错(就是这东西特别难查)
3.忘记更新子节点个数

下面是风格越发奇怪的代码(大多数是大白书上学来的)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N=100010,inf=10000010;
int n;

struct node
{
    node* ch[2];
    int r,s,v;
    node(int v):v(v){s=1; r=rand(); ch[0]=ch[1]=NULL;}
    bool operator < (const node& rhs) const {return r < rhs.r;}
    int cmp(int x)
    {
        if(x == v)return -1;
        return x < v ? 0 : 1 ;
    }
    void maintain(){
        s=1;
        if(ch[0] != NULL) s+=ch[0]->s;
        if(ch[1] != NULL) s+=ch[1]->s;
    }
};
node* rt=NULL;

void rotate(node* &o,int d)
{
    node* k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->maintain();k->maintain();
    o=k;
}

void ins(node* &o,int x)
{
    if(o == NULL){o=new node(x);return ;}
    int d=(x < o->v ? 0 : 1);ins(o->ch[d],x);
    if(o->ch[d] > o) rotate(o,d^1);
    o->maintain();
}

void del(node* &o,int x)
{
    if(o == NULL) return ;
    int d=o->cmp(x);
    if(d == -1)
    {

        if(o->ch[0] != NULL && o->ch[1] != NULL)
        {
            int d2=(o->ch[1]->r > o->ch[0]->r ? 0 : 1);
            rotate(o,d2);del(o->ch[d2],x);
        }
        else {if(o->ch[0] == NULL) o=o->ch[1];else o=o->ch[0];}
    }
    else del(o->ch[d],x);
    if(o != NULL) o->maintain();
}

int kth(node *o,int k)
{
    if(o == NULL || k > o->s || o <= 0) return 0;
    int s=(o->ch[0] == NULL ? 0 : o->ch[0]->s);
    if(k == s+1) return o->v;
    if(k <= s) return kth(o->ch[0], k);
    return kth(o->ch[1], k-s-1);
}

void rank(node *o,int x,int &ans,int k)
{
    if(o==NULL) return ;
    int ss=(o->ch[0] == NULL ? 0 : o->ch[0]->s);
    if(o->v < x) 
    {
        rank(o->ch[1],x,ans,k+ss+1);
        return ;
    }
    if(o->v == x) ans=min(ans,k+ss+1);
    rank(o->ch[0],x,ans,k);
}

void pre(node* o,int x,int &ans)
{
    if(o == NULL) return ;
    if(o->v < x)
    {
        ans=max(o->v, ans);
        pre(o->ch[1],x,ans);
        return ;
    }
    pre(o->ch[0],x,ans); 
}

void post(node* o,int x,int &ans)
{
    if(o == NULL) return ;
    if(o->v > x)
    {
        ans=min(o->v, ans);
        post(o->ch[0], x, ans);
        return ;
    }
    post(o->ch[1], x, ans); 
}

int read()
{
    int out=0, f=1; char c=getchar();
    while(c < '0' || c> '9') {if(c == '-') f=-1; c=getchar();}
    while(c >= '0' && c <= '9'){
        out=(out<<1)+(out<<3)+c-'0'; 
        c=getchar();
    }
    return out*f;
}

void solve()
{
    n=read();
    while(n--)
    {
        int opt=read(),x=read();
        if(opt == 1) ins(rt, x);
        if(opt == 2) del(rt, x);
        if(opt == 4) printf("%d\n",kth(rt, x));
        if(opt == 3) 
        {
            int ans3=inf;
            rank(rt, x,ans3,0);
            printf("%d\n",ans3);
        }
        if(opt == 5) 
        {
            int ans5=0-inf;
            pre(rt, x,ans5);
            printf("%d\n",ans5);
        }
        if(opt == 6) 
        {
            int ans6=inf;
            post(rt, x,ans6);
            printf("%d\n",ans6);
        }
    }
}


int main()
{
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值