替罪羊树(重量平衡树)

就是打了个板子
有个好板子:https://www.cnblogs.com/Hero-of-someone/p/7260332.html
这个只要改改代码风格就可以食用了
然后就是调参了qwq
0.8较为合适,可以跑到108ms
代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=' ';
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
#define ls ch[x][0]
#define rs ch[x][1]
const int N=3e6+5,inf=2e9;
const double alpha=0.75;
int n,sz,root,len;
int cur[N],ch[N][2],f[N],key[N],size[N];
inline bool balance(int x){
    return alpha*(double)size[x]>=size[ls] && alpha*(double)size[x]>=size[rs];
}
inline void recycle(int x){
    if(ls)recycle(ls);
    cur[++len]=x;
    if(rs)recycle(rs);
}
inline int build(int l,int r){
    if(l>r)return 0;
    int mid=(l+r)>>1,x=cur[mid];
    ls=build(l,mid-1);if(ls)f[ls]=x;
    rs=build(mid+1,r);if(rs)f[rs]=x;
    size[x]=size[ls]+size[rs]+1;
    return x;
}
inline void rebuild(int x){
    len=0;recycle(x);
    int fa=f[x],w=(ch[f[x]][1]==x);
    int cur=build(1,len);
    f[cur]=fa;ch[fa][w]=cur;
    if(x==root)root=cur;
}
inline void insert(int x){
    int now=root,cur=++sz,w;
    size[cur]=1;key[cur]=x;
    while(1){
        ++size[now];
        w=(x>=key[now]);
        if(ch[now][w])now=ch[now][w];
        else{
            f[ch[now][w]=cur]=now;
            break;
        }
    }
    int flag=0;
    for(int i=now;i;i=f[i])if(!balance(i))flag=i;
    if(flag)rebuild(flag);
}
inline int find(int x){
    int now=root;
    while(1){
        if(key[now]==x)return now;
        else now=ch[now][x>key[now]];
    }
}
inline void erase(int x){
    if(ls && rs){
        int cur=ls;
        while(ch[cur][1])cur=ch[cur][1];
        key[x]=key[cur];x=cur;
    }
    int cur=(ls)?ls:rs;
    int w=(ch[f[x]][1]==x);
    f[ch[f[x]][w]=cur]=f[x];
    for(int i=f[x];i;i=f[i])--size[i];
    if(x==root)root=cur;
}
inline int Rank(int v){
    int x=root,ans=0;
    while(x){
        if(v>key[x])ans+=size[ls]+1,x=rs;
        else x=ls;
    }
    return ans;
}
inline int Kth(int k){
    int x=root;
    while(1){
        if(k==size[ls]+1)return key[x];
        else if(k<=size[ls])x=ls;
        else k-=size[ls]+1,x=rs;
    }
}
inline int Pre(int v){
    int x=root,ans=-inf;
    while(x){
        if(v>key[x])ans=max(ans,key[x]),x=rs;
        else x=ls;
    }
    return ans;
}
inline int Next(int v){
    int x=root,ans=inf;
    while(x){
        if(v<key[x])ans=min(ans,key[x]),x=ls;
        else x=rs;
    }
    return ans;
}
int main(){
    key[1]=-inf;key[2]=inf;
    size[1]=2;size[2]=1;
    ch[1][1]=2;f[2]=1;
    sz=2;root=1;
    n=read();
    for(int i=1;i<=n;++i){
        int opt=read(),x=read();
        switch(opt){
            case 1:insert(x);break;
            case 2:erase(find(x));break;
            case 3:printf("%d\n",Rank(x));break;
            case 4:printf("%d\n",Kth(x+1));break;
            case 5:printf("%d\n",Pre(x));break;
            case 6:printf("%d\n",Next(x));break;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值