1. 程式人生 > 實用技巧 >Luogu3380 【模板】二逼平衡樹(樹套樹)

Luogu3380 【模板】二逼平衡樹(樹套樹)

Luogu3380 【模板】二逼平衡樹(樹套樹)

兩年沒寫樹套樹了,今天寫了一發線段樹套替罪羊樹。

結果替罪羊樹寫崩了,開啟板子\(QAQ\)

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define D double
#define N 50005
#define M 850000
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define s(x) a[x].siz
#define cnt(x) a[x].ct
#define val(x) a[x].v
using namespace std;
const int INF=2147483647;
const int FINF=-2147483647;
D alpha=0.8;
struct node
{
    int ch[2],siz,v,ct;
}a[M];
int n,m,w[N],rt[N << 2];
int opt,x,l,r,k;
namespace Scapegoat_Tree
{
    int tot=0,pool[M+5];
    int tp=0,q[N];
    int rp,rq;
    void Pre()
    {
        for (int i=M;i>=1;--i)
            pool[++tot]=i;
    }
    void Print(int x)
    {
        if (ls(x))
            Print(ls(x));
        printf("%d ",x);
        if (rs(x))
            Print(rs(x));
    }
    void print(int x)
    {
        Print(x);
        putchar('\n');
    }
    int newnode(int x)
    {
        int o=pool[tot--];
        ls(o)=rs(o)=0;
        val(o)=x,cnt(o)=s(o)=1;
        return o;
    }
    bool bad(int x)
    {
        return alpha*(D)s(x)<=(D)max(s(ls(x)),s(rs(x)));
    }
    void dfs(int x)
    {
        if (ls(x))
            dfs(ls(x));
        q[++tp]=x;
        if (rs(x))
            dfs(rs(x));
    }
    void update(int x)
    {
        s(x)=s(ls(x))+s(rs(x))+cnt(x);
    }
    int build(int l,int r)
    {
        if (l>r)
            return 0;
        if (l==r)
        {
            ls(q[l])=rs(q[l])=0;
            s(q[l])=cnt(q[l]);
            return q[l];
        }
        int mid=(l+r) >> 1;
        ls(q[mid])=build(l,mid-1);
        rs(q[mid])=build(mid+1,r);
        update(q[mid]);
        return q[mid];
    }
    void rebuild(int &x)
    {
        tp=0;
        dfs(x);
        x=build(1,tp);
    }
    void ins(int &x,int z)
    {
        if (!x)
        {
            x=newnode(z);
            return;
        }
        ++s(x);
        if (val(x)==z)
        {
            ++cnt(x);
            return;
        }
        int nxt=(z<val(x))?0:1;
        ins(a[x].ch[nxt],z);
        if (bad(x))
            rq=-1; else
        if (rq==-1)
            rp=x,rq=nxt;
    }
    void Ins(int &rt,int x)
    {
        rp=rq=0;
        ins(rt,x);
        if (rq==-1)
            rebuild(rt); else
        if (rp)
            rebuild(a[rp].ch[rq]);
    }
    int rmin(int &rt)
    {
        if (ls(rt))
        {
            int ret=rmin(ls(rt));
            if (bad(rt))
                rq=-1; else
            if (rq==-1)
                rp=rt,rq=0;
            update(rt);
            return ret;
        }
        int ret=rt;
        rt=rs(rt);
        return ret;
    }
    void del(int &x,int z)
    {
        if (!x)
            return;
        --s(x);
        if (val(x)==z)
        {
            --cnt(x);
            if (!cnt(x))
            {
                if (!ls(x))
                    pool[++tot]=x,x=rs(x); else
                if (!rs(x))
                    pool[++tot]=x,x=ls(x); else
                    {
                        int g=rmin(rs(x));
                        if (rq==-1)
                            rp=x,rq=1;
                        val(x)=val(g),cnt(x)=cnt(g);
                        update(x);
                        pool[++tot]=g;
                        if (bad(x))
                            rq=-1;
                    }
            }
            return;
        }
        int nxt=(z<val(x))?0:1;
        del(a[x].ch[nxt],z);
        if (bad(x))
            rq=-1; else
        if (rq==-1)
            rp=x,rq=nxt;
    }
    void Del(int &rt,int x)
    {
        rp=rq=0;
        del(rt,x);
        if (rq==-1)
            rebuild(rt); else
        if (rp)
            rebuild(a[rp].ch[rq]);
    }
    int prk(int x,int k)
    {
        int ans=0;
        while (x)
        {
            if (val(x)==k)
            {
                ans+=s(ls(x));
                return ans;
            }
            if (val(x)<k)
                ans+=s(ls(x))+cnt(x),x=rs(x); else
                x=ls(x);
        }
        return ans;
    }
    int rk(int x,int k)
    {
        return prk(x,k)+1;
    }
    int kth(int x,int k)
    {
        for (;;)
        {
            if (s(ls(x))>=k)
                x=ls(x); else
            if (s(ls(x))+cnt(x)>=k)
                return val(x); else
                k-=s(ls(x))+cnt(x),x=rs(x);
        }
    }
    int pre(int x,int k)
    {
        int ans=FINF;
        while (x)
        {
            if (val(x)<k)
                ans=max(ans,val(x)),x=rs(x); else
                x=ls(x);
        }
        return ans;
    }
    int succ(int x,int k)
    {
        int ans=INF;
        while (x)
        {
            if (val(x)>k)
                ans=min(ans,val(x)),x=ls(x); else
                x=rs(x);
        }
        return ans;
    }
};
namespace Segment_Tree
{
    void build(int p,int l,int r)
    {
        for (int i=l;i<=r;++i)
            Scapegoat_Tree::Ins(rt[p],w[i]);
        if (l==r)
            return;
        int mid=(l+r) >> 1;
        build(p << 1,l,mid);
        build(p << 1 | 1,mid+1,r);
    }
    int rk(int p,int l,int r,int x,int y,int z)
    {
        if (l==x && r==y)
            return Scapegoat_Tree::prk(rt[p],z);
        int mid=(l+r) >> 1;
        if (y<=mid)
            return rk(p << 1,l,mid,x,y,z); else
        if (x>mid)
            return rk(p << 1 | 1,mid+1,r,x,y,z); else
            return rk(p << 1,l,mid,x,mid,z)+rk(p << 1 | 1,mid+1,r,mid+1,y,z);
    }
    int Rk(int l,int r,int z)
    {
        return rk(1,1,n,l,r,z)+1;
    }
    int kth(int x,int y,int k)
    {
        int l=0,r=100000000,ans=-1;
        while (l<=r)
        {
            int mid=(l+r) >> 1;
            if (Rk(x,y,mid)<=k)
                ans=mid,l=mid+1; else
                r=mid-1;
        }
        return ans;
    }
    void modify(int p,int l,int r,int x,int z1,int z2)
    {
        Scapegoat_Tree::Del(rt[p],z1);
        Scapegoat_Tree::Ins(rt[p],z2);
        if (l==r)
            return;
        int mid=(l+r) >> 1;
        if (x<=mid)
            modify(p << 1,l,mid,x,z1,z2); else
            modify(p << 1 | 1,mid+1,r,x,z1,z2);
    }
    int pre(int p,int l,int r,int x,int y,int z)
    {
        if (l==x && r==y)
            return Scapegoat_Tree::pre(rt[p],z);
        int mid=(l+r) >> 1;
        if (y<=mid)
            return pre(p << 1,l,mid,x,y,z); else
        if (x>mid)
            return pre(p << 1 | 1,mid+1,r,x,y,z); else
            return max(pre(p << 1,l,mid,x,mid,z),pre(p << 1 | 1,mid+1,r,mid+1,y,z));
    }
    int succ(int p,int l,int r,int x,int y,int z)
    {
        if (l==x && r==y)
            return Scapegoat_Tree::succ(rt[p],z);
        int mid=(l+r) >> 1;
        if (y<=mid)
            return succ(p << 1,l,mid,x,y,z); else
        if (x>mid)
            return succ(p << 1 | 1,mid+1,r,x,y,z); else
            return min(succ(p << 1,l,mid,x,mid,z),succ(p << 1 | 1,mid+1,r,mid+1,y,z));
    }
};
int main()
{
    Scapegoat_Tree::Pre();
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        scanf("%d",&w[i]);
    Segment_Tree::build(1,1,n);
    for (int i=1;i<=m;++i)
    {
        scanf("%d",&opt);
        if (opt==1)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Segment_Tree::Rk(l,r,k));
        } else
        if (opt==2)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Segment_Tree::kth(l,r,k));
        } else
        if (opt==3)
        {
            scanf("%d%d",&x,&k);
            Segment_Tree::modify(1,1,n,x,w[x],k);
            w[x]=k;
        } else
        if (opt==4)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Segment_Tree::pre(1,1,n,l,r,k));
        } else
        if (opt==5)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Segment_Tree::succ(1,1,n,l,r,k));
        }
    }
    return 0;
}