【模板】替罪羊树

代码取材自BlackJack
Flag:我总有一天会把他辣眼睛的数组非递归式改成指针递归式!
bzoj 3224 普通平衡树

#include<bits/stdc++.h>
using namespace std;
const int N=100005,INF=1e9;
const double alpha=0.75;
struct sctree{int ch[2],fa,siz,val;}tree[N];
int root,tot;
void init(){
    tot=2;root=1;
    tree[1].val=-INF; tree[1].siz=2; tree[1].ch[1]=2;
    tree[2].val=INF;  tree[2].siz=1; tree[2].fa=1;
}
bool balance(int k){return (alpha*tree[k].siz>=1.0*tree[tree[k].ch[0]].siz)&&(alpha*tree[k].siz>=1.0*tree[tree[k].ch[1]].siz);}
int stac[N],top;
int build(int l,int r){
    if(l>r) return 0;
    int mid=l+r>>1,now=stac[mid];
    tree[now].ch[0]=build(l,mid-1);
    tree[now].ch[1]=build(mid+1,r);
    tree[tree[now].ch[1]].fa=tree[tree[now].ch[0]].fa=now;
    tree[now].siz=tree[tree[now].ch[0]].siz+tree[tree[now].ch[1]].siz+1;
    return now;
}
void seek(int k){
    if(!k)  return;
    seek(tree[k].ch[0]);
    stac[++top]=k;
    seek(tree[k].ch[1]);
}
void rebuild(int k){
    top=0;seek(k);
    int fa=tree[k].fa,son=(tree[fa].ch[1]==k),now=build(1,top);
    tree[now].fa=fa;
    tree[fa].ch[son]=now;
    if(root==k) root=now;
}
void insert(int x){
    int now=root,inv=0,i;
    bool son;
    tree[++tot].val=x;tree[tot].siz=1;
    while(1){
        ++tree[now].siz;
        son=(x>=tree[now].val);
        if(tree[now].ch[son])   now=tree[now].ch[son];
        else{
            tree[tot].fa=now;
            tree[now].ch[son]=tot;
            break;
        }
    }
    for(int i=tot;i;i=tree[i].fa)   if(!balance(i)) inv=i;
    if(inv) rebuild(inv);
}
inline int get_pos(int x){
    int now=root;
    while(tree[now].val!=x)
    now=x<tree[now].val ? tree[now].ch[0] : tree[now].ch[1];
    return now;
}
void del(int k){
    if(tree[k].ch[0] && tree[k].ch[1]){
        int goal=tree[k].ch[0];
        while(tree[goal].ch[1]) goal=tree[goal].ch[1];
        tree[k].val=tree[goal].val;
        k=goal;
    }
    int tmp=tree[k].ch[0] ? tree[k].ch[0] : tree[k].ch[1], son=(tree[tree[k].fa].ch[1]==k);
    tree[tree[k].fa].ch[son]=tmp;   tree[tmp].fa=tree[k].fa;
    if(root==k) root=tmp;
    while(tree[k].fa)   k=tree[k].fa,--tree[k].siz;
}
inline int Rank(int x){
    int now=root,res=0;
    while(now)
    tree[now].val<x ? (res+=tree[tree[now].ch[0]].siz+1,now=tree[now].ch[1]) : now=tree[now].ch[0];
    return res;
}
inline int Kth(int Kth){
    int now=root;
    while(1){
        if(tree[tree[now].ch[0]].siz+1==Kth)    return now;
        tree[tree[now].ch[0]].siz>=Kth ? now=tree[now].ch[0] : (Kth-=tree[tree[now].ch[0]].siz+1,now=tree[now].ch[1]);
    }
}
inline int Front(int x){
    int now=root,res;
    while(now)  tree[now].val<x ? (res=tree[now].val,now=tree[now].ch[1]) : now=tree[now].ch[0];
    return res;
}
inline int Back(int x){
    int now=root,res;
    while(now)  tree[now].val>x ? (res=tree[now].val,now=tree[now].ch[0]) : now=tree[now].ch[1];
    return res;
}
int main(){
    int n,opt,x;
    init();
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&opt,&x);
        switch(opt){
            case 1: insert(x);  break;
            case 2: del(get_pos(x));break;
            case 3: printf("%d\n",Rank(x));break;
            case 4: printf("%d\n",tree[Kth(x+1)].val);break;
            case 5: printf("%d\n",Front(x));break;
            case 6: printf("%d\n",Back(x));break;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zP1nG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值