替罪羊树

平衡树一种,基于重构的思想,插入点的时候判断某个子树不平衡到达一定程度就重构成一棵平衡的子树,具体判断不平衡是取一个alpha(约0.75),当某节点max(左子树,右子树)>=alpha×该节点总子树大小就重构。对于有删除操作的题目则维护两个size表示总的(不管删没删)和真实还存在的,在重构时去掉删掉的即可。

代码:

#pragma GCC optimize(3,"inline","Ofast")
#include<bits/stdc++.h>
#define db double
using namespace std;
inline void read(int &x)
{
    char c=getchar();x=0;int r=1;
    while(!isdigit(c))
    {
        if(c=='-')r=-1;
        c=getchar();
    }
    while(isdigit(c))x=(x<<3)+(x<<1)+c-48,c=getchar();
    x*=r;
}
inline void write(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)write(x/10);putchar(x%10+'0');}
    const int N = 1e5+10;
    const db apha = 0.75;
    struct gg{
        int ch[2],w,tsz,fsz;
        bool del;
    }node[N];
    int bin[2*N],tax[N],rt,pb,pt;
    void push_up(int x)
    {
        node[x].fsz=node[node[x].ch[0]].fsz+node[node[x].ch[1]].fsz+1;
        node[x].tsz=node[node[x].ch[0]].tsz+node[node[x].ch[1]].tsz+1;
    }
    bool check(int x)
    {return (db)max(node[node[x].ch[0]].tsz,node[node[x].ch[1]].tsz)>=(db)node[x].tsz*apha;}
    void dfs(int pos)
    {
        if(!pos)return;
        dfs(node[pos].ch[0]);
        if(!node[pos].del)tax[++pt]=pos;
        else bin[++pb]=pos;
        dfs(node[pos].ch[1]);
    }
    void build(int l,int r,int &nw)
    {
        int mid=(l+r)>>1;
        nw=tax[mid];
        if(l==r)
        {
            node[nw].del=0,node[nw].ch[0]=node[nw].ch[1]=0;
            node[nw].fsz=node[nw].tsz=1;
            return;
        }
        if(l<mid)build(l,mid-1,node[nw].ch[0]);else node[nw].ch[0]=0;
        if(mid<r)build(mid+1,r,node[nw].ch[1]);else node[nw].ch[1]=0;
        push_up(nw);
    }
    void pia(int &nw)
    {
        pt=0,dfs(nw);
        if(pt)build(1,pt,nw);
        else nw=0;
    }
    void ins(int &nw,int v)
    {
        if(!nw)
        {
            nw=bin[pb--];node[nw].del=0;node[nw].fsz=node[nw].tsz=1;
            node[nw].ch[0]=node[nw].ch[1]=0;node[nw].w=v;
            return;
        }
        node[nw].fsz++,node[nw].tsz++;
        if(node[nw].w>=v)ins(node[nw].ch[0],v);
        else ins(node[nw].ch[1],v);
        if(check(nw))pia(nw);
    }
    int rnk(int x)
    {
        int nw=rt,ans=1;
        while(nw)
        {
            if(node[nw].w>=x)nw=node[nw].ch[0];
            else
            {
                ans+=node[node[nw].ch[0]].tsz+(node[nw].del^1);
                nw=node[nw].ch[1];
            }
        }
        return ans;
    }
    int kth(int x)
    {
        int nw=rt;
        while(nw)
        {
            if(!node[nw].del&&node[node[nw].ch[0]].tsz+1==x)return node[nw].w;
            else if(node[node[nw].ch[0]].tsz>=x)nw=node[nw].ch[0];
            else x-=node[node[nw].ch[0]].tsz+(node[nw].del^1),nw=node[nw].ch[1];
        }
    }
    void del_pos(int &nw,int to)
    {
        if(!node[nw].del&&node[node[nw].ch[0]].tsz+1==to)
        {
            node[nw].del=1,node[nw].tsz--;return;
        }
        node[nw].tsz--;
        if(node[node[nw].ch[0]].tsz>=to)del_pos(node[nw].ch[0],to);//?
        else del_pos(node[nw].ch[1],to-node[node[nw].ch[0]].tsz-(node[nw].del^1));
    }
    void del_v(int nw)
    {
        del_pos(rt,rnk(nw));
        if((db)node[rt].fsz*apha>(db)node[rt].tsz)pia(rt);
    }
    void init()
    {
        pb=0;
        for(int i=200000;i>=1;i--)bin[++pb]=i;
    }
    int main()
    {
        init();
        int m,op,x;
        read(m);
        while(m--)
        {
            read(op),read(x);
            if(op==1)ins(rt,x);
            if(op==2)del_v(x);
            if(op==3)write(rnk(x)),puts("");
            if(op==4)write(kth(x)),puts("");
            if(op==5)write(kth(rnk(x)-1)),puts("");
            if(op==6)write(kth(rnk(x+1))),puts("");
        }
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值