[BZOJ3224] 普通平衡树 - splay

    事实证明我写了这么久的数学题 splay没有下降水平TAT

#include"stdio.h" 
#include"iostream"
using namespace std;
const int inf=(int)1e9;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct node {
    int key,siz; node *c[2],*fa; node();
    node(int v,node*c0,node*c1,node*pa);
    inline void pushup();
}Tnull,*null=&Tnull,*root;
node::node(){
    c[0]=c[1]=fa=null;
    key=0,siz=0;
}
node::node(int v,node*c0,node*c1,node*pa){
    c[0]=c0,c[1]=c1,fa=pa;
    key=v,siz=1;
}
inline void node::pushup(){
    siz=c[0]->siz+c[1]->siz+1;
}
int n,opt,x;

void rotate(node *x,node *&k){
    node *y=x->fa,*z=y->fa;
    if(root==y) root=x;
    if(z!=null) z->c[z->c[1]==y]=x;
    int l=y->c[1]==x,r=l^1;
    if(x->c[r]!=null) x->c[r]->fa=y;
    y->fa=x; x->fa=z;
    y->c[l]=x->c[r]; x->c[r]=y;
    y->pushup(); x->pushup();
}
void splay(node *x,node *&k){
     while (x!=k){
         node *y=x->fa,*z=y->fa;
         if(y!=k){
             if(z->c[0]==y ^ y->c[0]==x) rotate(x,k);
             else rotate(y,k);
         }
         rotate(x,k);
     }
}
node* find_smaller(int val,node*t){
    if(t==null) return null;
    if(t->key>=val) 
        return find_smaller(val,t->c[0]);
    node *q=find_smaller(val,t->c[1]);
    if(q==null||q->key<t->key) return t;
    return q;
}
node* find_bigger(int val,node*t){
    if(t==null) return null;
    if(t->key<=val) 
        return find_bigger(val,t->c[1]);
    node *q=find_bigger(val,t->c[0]);
    if(q==null||q->key>t->key) return t;
    return q;
}
node* find_rank(int rank,node *x){
    node* rk; if (x->c[0]->siz+1==rank) return x;
    if (x->c[0]->siz>=rank) rk=find_rank(rank,x->c[0]);
    else rk=find_rank(rank-x->c[0]->siz-1,x->c[1]);
    x->pushup(); return rk;
}
void smaller_split(int x){
    node*t=find_smaller(x,root); splay(t,root);
}
void bigger_split(int x){
    node*t=find_bigger(x,root); splay(t,root);
}
void insert(int x){
    smaller_split(x);
    node*nnode=new node(x,null,root->c[1],root);
    root->c[1]->fa=nnode; root->c[1]=nnode;
    root->c[1]->pushup(); root->pushup();
}
void delit(int x){
    smaller_split(x); node*t;
    t=find_rank(root->c[0]->siz+2,root); splay(t,root->c[1]);
    node*del=root->c[1]; root->c[1]=root->c[1]->c[1];
    root->c[1]->fa=root; delete del;
}
int get_rank(int x){
    smaller_split(x);
    return root->c[0]->siz+2;
}
int result_rank(int rk){
    node*t=find_rank(rk,root);
    return t->key;
}
int pre(int x){
    smaller_split(x);
    return root->key;
}
int npre(int x){
    bigger_split(x);
    return root->key;
}

int main(){
    root=new node(-inf,null,new node(inf,null,null,null),null);
    n=read(); root->c[1]->fa=root; root->siz=2;
    for(int i=1;i<=n;i++){
        opt=read(); x=read();
        if(opt==1) insert(x);
        else if(opt==2) delit(x);
        else { opt-=3;
             int ans=opt&2?opt&1?npre(x):pre(x):opt&1?result_rank(x+1):get_rank(x)-1;
             printf("%d\n",ans);
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值