平衡树—替罪羊树模板(洛谷3369)

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxn=1e5+5;
const double alpha=0.75;
struct node
{
    int l,r,val;
    int siz,fact;
    bool exist;
}tzy[maxn];
int cnt,root;
void newnode(int &now,int val)
{
    now=++cnt;
    tzy[now].val=val;
    tzy[now].siz=tzy[now].fact=1;
    tzy[now].exist=true;
}
bool imbalance(int now)
{
    if(max(tzy[tzy[now].l].siz,tzy[tzy[now].r].siz)>tzy[now].siz*alpha
       ||tzy[now].siz-tzy[now].fact>tzy[now].siz*0.3)
        return true;
    return false;
}
vector<int> v;
void ldr(int now)
{
    if(!now)
        return;
    ldr(tzy[now].l);
    if(tzy[now].exist)
        v.push_back(now);
    ldr(tzy[now].r);
}
void lift(int l,int r,int &now)
{
    if(l==r)
    {
        now=v[l];
        tzy[now].l=tzy[now].r=0;
        tzy[now].siz=tzy[now].fact=1;
        return;
    }
    int m=(l+r)>>1;
    while(l<m&&tzy[v[m]].val==tzy[v[m-1]].val)
        m--;
    now=v[m];
    if(l<m)
        lift(l,m-1,tzy[now].l);
    else
        tzy[now].l=0;
    lift(m+1,r,tzy[now].r);
    tzy[now].siz=tzy[tzy[now].l].siz+tzy[tzy[now].r].siz+1;
    tzy[now].fact=tzy[tzy[now].l].fact+tzy[tzy[now].r].fact+1;
}
void rebuild(int &now)
{
    v.clear();
    ldr(now);
    if(v.empty())
    {
        now=0;
        return;
    }
    lift(0,v.size()-1,now);
}
void update(int now,int endd)
{
    if(!now)
        return;
    if(tzy[endd].val<tzy[now].val)
        update(tzy[now].l,endd);
    else
        update(tzy[now].r,endd);
    tzy[now].siz=tzy[tzy[now].l].siz+tzy[tzy[now].r].siz+1;
}
void check(int &now,int endd)
{
    if(now==endd)
        return;
    if(imbalance(now))
    {
        rebuild(now);
        update(root,now);
        return;
    }
    if(tzy[endd].val<tzy[now].val)
        check(tzy[now].l,endd);
    else
        check(tzy[now].r,endd);
}
void ins(int &now,int val)
{
    if(!now)
    {
        newnode(now,val);
        check(root,now);
        return;
    }
    tzy[now].siz++;
    tzy[now].fact++;
    if(val<tzy[now].val)
        ins(tzy[now].l,val);
    else
        ins(tzy[now].r,val);
}
void del(int now,int val)
{
    if(tzy[now].exist&&tzy[now].val==val)
    {
        tzy[now].exist=false;
        tzy[now].fact--;
        check(root,now);
        return;
    }
    tzy[now].fact--;
    if(val<tzy[now].val)
        del(tzy[now].l,val);
    else
        del(tzy[now].r,val);
}
int getrank(int val)
{
    int now=root,rankk=1;
    while(now)
    {
        if(val<=tzy[now].val)
            now=tzy[now].l;
        else
        {
            rankk+=tzy[now].exist+tzy[tzy[now].l].fact;
            now=tzy[now].r;
        }
    }
    return rankk;
}
int getnum(int rankk)
{
    int now=root;
    while(now)
    {
        if(tzy[now].exist&&tzy[now].exist+tzy[tzy[now].l].fact==rankk)
            break;
        else if(tzy[tzy[now].l].fact>=rankk)
            now=tzy[now].l;
        else
        {
            rankk-=tzy[now].exist+tzy[tzy[now].l].fact;
            now=tzy[now].r;
        }
    }
    return tzy[now].val;
}
int main()
{
    int t,opt,x;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&opt,&x);
        switch(opt)
        {
        case 1:
            ins(root,x);
            break;
        case 2:
            del(root,x);
            break;
        case 3:
            printf("%d\n",getrank(x));
            break;
        case 4:
            printf("%d\n",getnum(x));
            break;
        case 5:
            printf("%d\n",getnum(getrank(x)-1));
            break;
        case 6:
            printf("%d\n",getnum(getrank(x+1)));
            break;
        }
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值