[模板] 替罪羊树

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cctype>
#include<cstdio>
#include<cctype> 

int rd() {
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c)) {
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret*f;
}

const int MAXN=200000;
const double alpha = 0.75;
struct Node{
    int l,r,val;
    int size,cnt;
    bool exist;
}node[MAXN];
int cur[MAXN];
int mem[MAXN];
int root,pos,pool,cnt,to_rebuild;

bool isbad(int now){
    if((double)node[now].cnt*alpha<=(double)std::max(node[node[now].l].cnt,node[node[now].r].cnt))return true;
    return false;
}

void dfs(int now){
    if(!now) return;
    dfs(node[now].l);
    if(node[now].exist)cur[++pos]=now;
    else mem[++pool]=now;
    dfs(node[now].r);
}

void build(int L,int R,int &now){
    int mid=(L+R)>>1;
    now=cur[mid];
    if(L==R){
        node[now].l=node[now].r=0;
        node[now].size=node[now].cnt=1;
        return;
    }
    if(L<R)build(L,mid-1,node[now].l);
    else node[now].l=0;
    build(mid+1,R,node[now].r);
    node[now].size=node[node[now].l].size+node[node[now].r].cnt+1;
    node[now].cnt=node[node[now].l].cnt+node[node[now].r].cnt+1;
}

void rebuild(int &now){
    pos=0;
    dfs(now);
    if(pos)build(1,pos,now);
    else now=0;
}

int rank(int tar){
    int now=root,ans=1;
    while(now){
        if(node[now].val>=tar)now=node[now].l;
        else{
            ans+=node[node[now].l].cnt+node[now].exist;
            now=node[now].r;
        }
    }
    return ans;
}

void inst(int &now,int val){
    if(!now){
        now=mem[pool--];
        node[now].val=val;
        node[now].cnt=node[now].size=1;
        node[now].exist=true;
        node[now].l=node[now].r=0;
        return;
    }
    node[now].size++;node[now].cnt++;
    if(node[now].val>=val) inst(node[now].l,val);
    else inst(node[now].r,val);
    if(!isbad(now)){
        if(to_rebuild){
            if(node[now].l==to_rebuild)rebuild(node[now].l);
            else rebuild(node[now].r);
            to_rebuild=0;
        }
    }else to_rebuild=now;
}

void del_pos(int &now,int tar){
    if(node[now].exist&&node[node[now].l].cnt+1==tar){
        node[now].exist = false;
        node[now].cnt--;
        return;
    }
    node[now].cnt--;
    if(node[node[now].l].cnt+node[now].exist>=tar) del_pos(node[now].l,tar);
    else del_pos(node[now].r,tar-node[node[now].l].cnt-node[now].exist);
}

void del_val(int tar){
    del_pos(root,rank(tar));
    if((double)node[root].size*alpha>node[root].cnt) rebuild(root);
}

int kth(int tar){
    int now=root;
    while(now){
        if(node[now].exist&&node[node[now].l].cnt+1==tar) return node[now].val;
        else if(node[node[now].l].cnt>=tar) now=node[now].l;
        else{
            tar-=node[node[now].l].cnt+node[now].exist;//
            now=node[now].r;
        }
    }
    return 0;
}

int main() {
    int num,a,b;
    root=0;
    for(int i=MAXN; i>=1; --i)mem[++pool]=i; //初始化内存池
    num=rd();
    while(num--) {
        a=rd();
        b=rd();
        switch(a) {
            case 1: {
                inst(root,b);
                break;
            }
            case 2: {
                del_val(b);
                break;
            }
            case 3: {
                printf("%d\n",rank(b));
                break;
            }
            case 4: {
                printf("%d\n",kth(b));
                break;
            }
            case 5: {
                printf("%d\n",kth(rank(b)-1));
                break;
            }
            case 6: {
                printf("%d\n",kth(rank(b+1)));
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/gh0stcai/article/details/80068670