普通平衡树

Treap

#include <iostream>
#include<cstdio>
#include <queue>
#include <stack>
using namespace std;
const int maxn=1e5+50;
int fa[maxn];
int ch[maxn][2];
int dat[maxn];
int sz[maxn];
int rep[maxn];
int val[maxn];
stack<int> ava;
#define left(i) (ch[i][0])
#define right(i) (ch[i][1])
#define sons(i,j) (ch[i][j])
#define lorr(i,j) (dat[i]>dat[j])
void destroy_node(int i,int f)
{
    fa[i]=ch[i][0]=ch[i][1]=rep[i]=sz[i]=0;
    ava.push(i);
}
int seed=1234;
const int maxx=0x3f3f3f3f<<1;
int rand()
{
    return int(seed=seed*123456LL%maxx);
}
int ff=0;
int new_node(int data,int f)
{
    int n=ava.top();
    ava.pop();
    fa[n]=f;
    rep[n]=sz[n]=1;
    val[n]=rand();
    dat[n]=data;
    sons(f,lorr(n,f))=n;
    return n ;
}
int init_ava()
{
    for(int i=maxn-1; i; i--)
        ava.push(i);
}
int root=0;
void updata(int i)
{
    sz[i]=sz[left(i)]+sz[right(i)]+rep[i];
}
void brotate(int i)
{
    if(!i)return ;
    int f=fa[i],ff=fa[f];
    sons(ff,lorr(f,ff))=0;
    sons(ff,lorr(i,ff))=i;
    fa[i]=ff;
    fa[f]=i;
    sons(f,lorr(i,f))=sons(i,!lorr(i,f));
    fa[sons(i,!lorr(i,f))]=f;
    sons(i,!lorr(i,f))=f;
    if(!fa[i])root=i;
    updata(f);
    updata(i);
   // show(9);
}
int f=0;
void inserts(int data,int index)
{
    if(!index)
    {

        int t=new_node(data,f);
        if(!root)root=t;
        return ;
    }
    else if(dat[index]==data) {
        rep[index]++;
        sz[index]++;
        return ;
    }
    else {
        f=index;
        if(data>dat[index]) {
            inserts(data,right(index));
        }
        else inserts(data,left(index));
        sz[index]++;
    }
    index=sons(index,data>dat[index]);
    if(fa[index]&&val[index]>val[fa[index]])
    {
        brotate(index);
    }

}
int ends1,rep1;
void clears(){ends1=f=0;rep1=1;}
void dels(int data,int &index)
{
    if(dat[index]==data&&rep[index]>1){
        rep[index]--;
        sz[index]--;
    return ;
    }
    if(dat[index]==data||right(index)==0&&data>dat[index]||left(index)==0&&data<dat[index])
    {
        if(right(index)==0||left(index)==0){
        int sf=right(index)+left(index);
        ends1=dat[index];
        rep1=rep[index];
        fa[sf]=fa[index];
        int t=index;
        destroy_node(index,fa[index]);
        index=sf;
        }
        else
        {
            dels(data+1,left(index));
            dat[index]=ends1;
            sz[index]-=1;
            rep[index]=rep1;
            rep1=1;
        }
        return ;
    }
    dels(data,sons(index,data>dat[index]));
    sz[index]-=rep1;
}
int get_rank(int data,int index) {
    if(dat[index]==data) {
        return sz[left(index)]+1;
    }
    int c=(data>dat[index])?1:0;
    int d=c?sz[left(index)]+rep[index]:0;
    return d+get_rank(data,sons(index,c));
}
int get_item(int locat,int index) {
    if(locat>sz[left(index)]&&locat<=sz[left(index)]+rep[index])
        return dat[index];
        int d=locat>sz[left(index)]+rep[index];
    return get_item(d?locat-rep[index]-sz[left(index)]:locat,sons(index,d));
}
inline int get_prev(int data,int index,int ans)
{
    if(!index)
        return ans;
    int d=data>dat[index];
    return get_prev(data,sons(index,d),d?dat[index]:ans);

}
inline int get_lat(int data,int index,int ans)
{
    if(!index)
        return ans;
    int d=data<dat[index];
    return get_lat(data,sons(index,!d),d?dat[index]:ans);
}
int y=0;
int choice(int ch,int dat)
{
clears();
ch--;
    switch(ch)
    {
    case 0:
        inserts(dat,root);
        break;
    case 1:
        dels(dat,root);
        break;
    case 2:
        printf("%d\n",get_rank(dat,root));
        break;
    case 3:
        printf("%d\n",get_item(dat,root));
        break;
    case 4:
        printf("%d\n",get_prev(dat,root,-maxx));
        break;
    case 5:
        printf("%d\n",get_lat(dat,root,maxx));;
        break;
    }
}
int main()
{
    init_ava();
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        choice(x,y);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值