平衡树:treap学习笔记(2)

上一次写了旋转的treap(代码非常简单。
这次我们来写无旋的treap。这个treap没有旋转操作。
有两个基本操作:合并、分裂。
插入和删除时都使用到了这两个操作,感觉很妙呀qaq。
具体的解释详见:https://wenku.baidu.com/view/09fbf8147c1cfad6195fa7f0.html
还有zcy的代码:https://www.cnblogs.com/zcysky/p/6876646.html
还有http://blog.csdn.net/wyj_jenny/article/details/78559603

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair

typedef pair<int,int>par;
const int MAXN=1e5;
const int INF=1e9;

int rt=0,cnt=0;

struct treap{
    int lson[MAXN],rson[MAXN],size[MAXN],prio[MAXN],w[MAXN];
    inline void pushup(int p){size[p]=size[lson[p]]+size[rson[p]]+1;}
    par split(int p,int x){
        if(!x)return mp(0,p);
        int l=lson[p],r=rson[p];
        if(x<=size[l]){//下面千万别打错。
            par tem=split(l,x);
            lson[p]=tem.second;pushup(p);return mp(tem.first,p);
        }
        par tem=split(r,x-size[l]-1);
        rson[p]=tem.first;pushup(p);return mp(p,tem.second);
    }
    int merge(int x,int y){
        if(!x){
            pushup(y);return y;
        }
        if(!y){
            pushup(x);return x;
        }
        if(prio[x]<prio[y]){
            rson[x]=merge(rson[x],y);pushup(x);return x;
        }
        else {
            lson[y]=merge(x,lson[y]);pushup(y);return y;
        }
    }
    int queryrank(int p,int x){
        int ans=0,tem=INF;
        while(p){//p的转换,顺序别打反。
            if(x==w[p])tem=min(tem,ans+size[lson[p]]+1);
            if(x>w[p])ans+=size[lson[p]]+1,p=rson[p];
            else p=lson[p];
        }
        return tem==INF?ans:tem;
    }
    void insert(int x){
        int k=queryrank(rt,x);par tem=split(rt,k);
        w[++cnt]=x;prio[cnt]=rand();size[cnt]=1;
        rt=merge(tem.first,cnt);rt=merge(rt,tem.second);
    }
    void del(int x){
        int k=queryrank(rt,x);par t1=split(rt,k),t2=split(t1.first,k-1);
        rt=merge(t2.first,t1.second);
    }
    int findnum(int p,int x){
        for(;;){
            if(x==size[lson[p]]+1)return w[p];
            if(x<size[lson[p]]+1)p=lson[p];
            else x=x-size[lson[p]]-1,p=rson[p];
        }
    }
    int findpre(int p,int x){
        int ans=-INF;
        while(p){
            if(x>w[p]){
                ans=max(ans,w[p]);
                p=rson[p];
            }
            else p=lson[p];
        }
        return ans;
    }
    int findsub(int p,int x){
        int ans=INF;
        while(p){
            if(x<w[p]){
                ans=min(ans,w[p]);
                p=lson[p];
            }
            else p=rson[p];
        }
        return ans;
    }
}treap;

int main(){
    int n,opt,x;
    scanf("%d",&n);srand(82602002);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&opt,&x); 
        if(opt==1)treap.insert(x);
        if(opt==2)treap.del(x);
        if(opt==3)printf("%d\n",treap.queryrank(rt,x));
        if(opt==4)printf("%d\n",treap.findnum(rt,x));
        if(opt==5)printf("%d\n",treap.findpre(rt,x));
        if(opt==6)printf("%d\n",treap.findsub(rt,x));
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值