替罪羊树OI-WIKI板子求调
查看原帖
替罪羊树OI-WIKI板子求调
740948
rb_tree楼主2024/10/13 09:58

rt

#include<cstdio>
#include<set>
using namespace std;
inline int read()
{
    int x=0,w=1;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*w;
}
inline void write(int x) 
{
    if(x<0) 
    { 
        x=-x;
        putchar('-');
    }
    if(x>=10) write(x/10);
    putchar((x%10)^48);
}
const int MAXN=10005;
const double alpha=0.7;
int cnt,rt,w[MAXN],lc[MAXN],rc[MAXN],wn[MAXN],s[MAXN],sz[MAXN],sd[MAXN],ldr[MAXN];
void Calc(int k) 
{
    s[k]=s[lc[k]]+s[rc[k]]+1;
    sz[k]=sz[lc[k]]+sz[rc[k]]+wn[k];
    sd[k]=sd[lc[k]]+sd[rc[k]]+(wn[k]!=0);
}
bool CanRbu(int k) 
{
    return wn[k]&&(alpha*s[k]<=(double)std::max(s[lc[k]],s[rc[k]])||(double)sd[k] <= alpha * s[k]);
}
void Rbu_Flatten(int& ldc, int k) 
{
    if(!k) return;
    Rbu_Flatten(ldc,lc[k]);
    if(wn[k]) ldr[ldc++]=k;
    Rbu_Flatten(ldc,rc[k]);
}
int Rbu_Build(int l, int r)
{
    int mid=l+r>>1;
    if(l>=r) return 0;
    lc[ldr[mid]]=Rbu_Build(l,mid);
    rc[ldr[mid]]=Rbu_Build(mid+1,r);
    Calc(ldr[mid]);
    return ldr[mid];
}
void Rbu(int& k) 
{
    int ldc=0;
    Rbu_Flatten(ldc,k);
    k=Rbu_Build(0,ldc);
}
void Ins(int& k, int p) 
{
    if(!k) 
    {
        k=++cnt;
        if(!rt) rt=1;
        w[k]=p;
        lc[k]=rc[k]=0;
        wn[k]=s[k]=sz[k]=sd[k]=1;
    }
    else 
    {
        if(w[k]==p) wn[k]++;
        else if(w[k]<p) Ins(rc[k],p);
        else Ins(lc[k],p);
        Calc(k);
        if(CanRbu(k)) Rbu(k);
    }
}
int MyUprGrt(int k, int p) 
{
    if(!k) return 0;
    else if(w[k]==p&&wn[k]) return sz[lc[k]];
    else if(w[k]<p) return sz[lc[k]]+wn[k]+MyUprGrt(rc[k],p);
    else return MyUprGrt(lc[k],p);
}
int MyUprBd(int k, int p) 
{
  if(!k) return 1;
  else if(w[k]==p&&wn[k]) return sz[lc[k]]+1+wn[k];
  else if(p<w[k]) return MyUprBd(lc[k],p);
  else return sz[lc[k]]+wn[k]+MyUprBd(rc[k],p);
}
int MyAt(int k, int p) 
{
    if(!k) return 0;
    else if(sz[lc[k]]<p&&p<=sz[lc[k]]+wn[k]) return w[k];
    else if(sz[lc[k]]+wn[k]<p) return MyAt(rc[k],p-sz[lc[k]]-wn[k]);
    else return MyAt(lc[k],p);
}
void Del(int& k, int p)
{
    if(!k) return;
    else 
    {
        if(w[k]==p) 
        {
            if(wn[k]) wn[k]--;
        } 
        else 
        {
            if(w[k]<p) Del(rc[k],p);
            else Del(lc[k],p);
        }
        Calc(k);
        if(CanRbu(k)) Rbu(k);
    }
}
int MyPre(int k,int p) { return MyAt(k,MyUprGrt(k,p)); }
int MyPost(int k,int p) { return MyAt(k,MyUprBd(k,p)); }
int main()
{
    int q=read();
    set<int> vis;
    for(int i=1;i<=q;i++)
    {
        int op=read();
        if(op==1)
        {
            int x=read();
            if(!vis.count(x)) Ins(rt,x);
            write(MyUprGrt(rt,x)+1);
            if(!vis.count(x)) Del(rt,x);
            putchar('\n');
        }
        if(op==2)
        {
            int x=read();
            write(MyAt(rt,x));
            putchar('\n');
        }
        if(op==3)
        {
            int x=read();
            write(MyPre(rt,x));
            putchar('\n');
        }
        if(op==4)
        {
            int x=read();
            write(MyPost(rt,x));
            putchar('\n');
        }
        if(op==5)
        {
            int x=read();
            Ins(rt,x);
            vis.insert(x);
        }
    }
    return 0;
}
2024/10/13 09:58
加载中...