[BZOJ][替罪羊树]3224 普通平衡树

题目就不说了,平衡树裸题。
为什么我的所有平衡树都比别人的慢上一大截啊。

#include <cstdio>
using namespace std;
const int N=100002;
const double alpha=0.721,sin=0.5;
inline char tc(void){
    static char fl[N],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,N,stdin),A==B)?EOF:*A++;
}
inline int read(void){
    int a=0,f=1;static char c;
    while((c=tc())<'0'||c>'9')c=='-'?f=-1:0;
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a*f;
}
inline int max(int a,int b){
    return a>b?a:b;
}
int v[N],sz[N],ls[N],rs[N],cnt[N],exist[N],n,root,tot,que[N],tque,*sgt;
inline void update(int x){
    sz[x]=exist[x]+sz[ls[x]]+sz[rs[x]],
    cnt[x]=1+cnt[ls[x]]+cnt[rs[x]];
    return ;
}
void dfs(int x){
    if(ls[x])dfs(ls[x]);
    if(exist[x])que[++tque]=x;
    if(rs[x])dfs(rs[x]);
    return ;
}
int build(int l,int r){
    if(l>r)return 0;
    int mid=l+r>>1,x=que[mid];
    sz[x]=cnt[x]=exist[x]=1,
    ls[x]=build(l,mid-1),
    rs[x]=build(mid+1,r);
    update(x);
    return x;
}
void rebuild(int *x){
    tque=0,dfs(*x),*x=build(1,tque);
    return ;
}
bool isbad(int x){
    if(cnt[x]*alpha+5<max(cnt[ls[x]],cnt[rs[x]]))
        return 1;
    if(sz[x]+5<cnt[x]*sin)return 1;
    return 0;
}
void insert(int &x,int d){
    if(!x){
        x=++tot,
        v[x]=d,
        sz[x]=cnt[x]=exist[x]=1,
        ls[x]=rs[x]=0;
        return ;
    }
    if(d<=v[x])insert(ls[x],d);
    else insert(rs[x],d);
    update(x);
    if(isbad(x))sgt=&x;
    return ;
}
void del(int &x,int d){
    int num=sz[ls[x]]+exist[x];
    if(num==d&&exist[x]){
        --sz[x],
        exist[x]=0;
        return ;
    }
    if(d<=num)del(ls[x],d);
    else del(rs[x],d-num);
    update(x);
    if(isbad(x))sgt=&x;
    return ;
}
void ins(int d){
    sgt=NULL,
    insert(root,d);
    if(sgt)rebuild(sgt);
    return ;
}
void erase(int d){
    sgt=NULL,
    del(root,d);
    if(sgt)rebuild(sgt);
    return ;
}
int get_low(int x,int d){
    if(!x)return 0;
    if(d<=v[x]) return get_low(ls[x],d);
    else return sz[ls[x]]+exist[x]+get_low(rs[x],d);
}
int findkth(int x,int d){
    int num=sz[ls[x]]+exist[x];
    if(num==d&&exist[x])return v[x];
    if(d<=num)return findkth(ls[x],d);
    else return findkth(rs[x],d-num);
}
int main(void){
    register int i,x,y;
    n=read();
    for (i=1;i<=n;++i){
        x=read(),y=read();
        switch(x){
            case 1:ins(y);break;
            case 2:erase(get_low(root,y)+1);break;
            case 3:printf("%d\n",get_low(root,y)+1);break;
            case 4:printf("%d\n",findkth(root,y));break;
            case 5:printf("%d\n",findkth(root,get_low(root,y)));break;
            default :printf("%d\n",findkth(root,get_low(root,y+1)+1));break;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值