「模板」 树套树

Posted Capella

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「模板」 树套树相关的知识,希望对你有一定的参考价值。

「模板」 树套树

<题目链接>


线段树套 SBT。

有生以来写过的最长代码。

虽然能过,但我删除 SBT 点的时候没回收内存!写了就 RE!

先放上来吧,回收内存调出来了再修改qwq。

#include <algorithm>
#include <climits>
#include <cstdio>
using std::max;
using std::min;
const int MAXN=50010;
int n,m;
class SegmentTree
{
    private:
        int a[MAXN];
        class SBT
        {
            private:
                struct Node
                {
                    int v,size;
                    Node *c[2];
                    Node(int v):v(v),size(1)
                    {
                        c[0]=c[1]=nullptr;
                    }
                    ~Node(void)
                    {
                        if(c[0]!=nullptr)
                            delete c[0];
                        if(c[1]!=nullptr)
                            delete c[1];
                    }
                    int Size(bool p)
                    {
                        return c[p]!=nullptr ? c[p]->size : 0;
                    }
                    int SubSize(bool p,bool q)
                    {
                        return c[p]!=nullptr ? c[p]->Size(q) : 0;
                    }
                    void Update(void)
                    {
                        size=Size(0)+Size(1)+1;
                    }
                }*rt;
                void Rotate(Node* &i,bool p)
                {
                    Node *t=i->c[!p];
                    i->c[!p]=t->c[p];
                    t->c[p]=i;
                    i->Update();
                    (i=t)->Update();
                }
                void Maintain(Node* &i,bool p)
                {
                    int t=i->Size(!p);
                    if(t<i->SubSize(p,p))
                        Rotate(i,!p);
                    else if(t<i->SubSize(p,!p))
                    {
                        Rotate(i->c[p],p);
                        Rotate(i,!p);
                    }
                    else
                        return;
                    Maintain(i->c[0],0);
                    Maintain(i->c[1],1);
                    Maintain(i,0);
                    Maintain(i,1);
                }
                void Insert(Node* &i,int x)
                {
                    if(i==nullptr)
                    {
                        i=new Node(x);
                        return;
                    }
                    bool p=x>i->v;
                    ++i->size;
                    Insert(i->c[p],x);
                    Maintain(i,p);
                }
                void Delete(Node* &i,int x)
                {
                    if(i==nullptr)
                        return;
                    if(x==i->v)
                        if(i->c[1]==nullptr)
                        {
                            Node *t=i->c[0];
                            delete i;
                            i=t;
                            return;
                        }
                        else
                        {
                            Node *t=i->c[1];
                            while(t->c[0]!=nullptr)
                                t=t->c[0];
                            i->v=t->v;
                            Delete(i->c[1],t->v);
                        }
                    else
                        Delete(i->c[x>i->v],x);
                    i->Update();
                }
            public:
                SBT(int* a,int l,int r):rt(nullptr)
                {
                    for(int i=l;i<=r;++i)
                        Insert(a[i]);
                }
                ~SBT(void)
                {
                    delete rt;
                }
                void Insert(int x)
                {
                    Insert(rt,x);
                }
                void Delete(int x)
                {
                    Delete(rt,x);
                }
                int Rank(int x)
                {
                    int ans=1;
                    Node *i=rt;
                    while(i!=nullptr)
                        if(x>i->v)
                        {
                            ans+=i->Size(0)+1;
                            i=i->c[1];
                        }
                        else
                            i=i->c[0];
                    return ans-1;
                }
                int Prev(int x)
                {
                    int ans=-INT_MAX;
                    Node *i=rt;
                    while(i!=nullptr)
                        if(x>i->v)
                        {
                            ans=max(ans,i->v);
                            i=i->c[1];
                        }
                        else
                            i=i->c[0];
                    return ans;
                }
                int Next(int x)
                {
                    int ans=INT_MAX;
                    Node *i=rt;
                    while(i!=nullptr)
                        if(x<i->v)
                        {
                            ans=min(ans,i->v);
                            i=i->c[0];
                        }
                        else
                            i=i->c[1];
                    return ans;
                }
        };
        struct Node
        {
            SBT *T;
            int l,r;
            Node *c[2];
            Node(SBT* T,int l,int r):T(T),l(l),r(r)
            {
                c[0]=c[1]=nullptr;
            }
            ~Node(void)
            {
                delete T;
                if(c[0]!=nullptr)
                    delete c[0];
                if(c[1]!=nullptr)
                    delete c[1];
            }
        }*rt;
        void Build(Node* &i,int l,int r)
        {
            i=new Node(new SBT(a,l,r),l,r);
            if(l^r)
            {
                int mid=l+r>>1;
                Build(i->c[0],l,mid);
                Build(i->c[1],mid+1,r);
            }
        }
        int Rank(Node* i,int l,int r,int k)
        {
            if(l==i->l && r==i->r)
                return i->T->Rank(k);
            int mid=i->l+i->r>>1;
            if(r<=mid)
                return Rank(i->c[0],l,r,k);
            else if(l>mid)
                return Rank(i->c[1],l,r,k);
            else
                return Rank(i->c[0],l,mid,k)+Rank(i->c[1],mid+1,r,k);
        }
        void Modify(Node* i,int pos,int k)
        {
            i->T->Delete(a[pos]);
            i->T->Insert(k);
            if(pos==i->l && pos==i->r)
                return;
            int mid=i->l+i->r>>1;
            if(pos>mid)
                Modify(i->c[1],pos,k);
            else
                Modify(i->c[0],pos,k);
        }
        int Prev(Node* i,int l,int r,int k)
        {
            if(l==i->l && r==i->r)
                return i->T->Prev(k);
            int mid=i->l+i->r>>1;
            if(r<=mid)
                return Prev(i->c[0],l,r,k);
            else if(l>mid)
                return Prev(i->c[1],l,r,k);
            else
                return max(Prev(i->c[0],l,mid,k),Prev(i->c[1],mid+1,r,k));
        }
        int Next(Node* i,int l,int r,int k)
        {
            if(l==i->l && r==i->r)
                return i->T->Next(k);
            int mid=i->l+i->r>>1;
            if(r<=mid)
                return Next(i->c[0],l,r,k);
            else if(l>mid)
                return Next(i->c[1],l,r,k);
            else
                return min(Next(i->c[0],l,mid,k),Next(i->c[1],mid+1,r,k));
        }
    public:
        SegmentTree(int n):rt(nullptr)
        {
            for(int i=1;i<=n;++i)
                scanf("%d",&a[i]);
            Build(rt,1,n);
        }
        ~SegmentTree(void)
        {
            delete rt;
        }
        void Rank(void)
        {
            int l,r,k;
            scanf("%d %d %d",&l,&r,&k);
            printf("%d\n",Rank(rt,l,r,k)+1);
        }
        void Find(void)
        {
            int l,r,k,left=0,right=int(1e8),mid;
            scanf("%d %d %d",&l,&r,&k);
            while(left<right)
            {
                int mid=left+right>>1;
                if(k>Rank(rt,l,r,mid))
                    left=mid+1;
                else
                    right=mid;
            }
            printf("%d\n",left-1);
        }
        void Modify(void)
        {
            int pos,k;
            scanf("%d %d",&pos,&k);
            Modify(rt,pos,k);
            a[pos]=k;
        }
        void Prev(void)
        {
            int l,r,k;
            scanf("%d %d %d",&l,&r,&k);
            printf("%d\n",Prev(rt,l,r,k));
        }
        void Next(void)
        {
            int l,r,k;
            scanf("%d %d %d",&l,&r,&k);
            printf("%d\n",Next(rt,l,r,k));
        }
};
int main(int argc,char** argv)
{
    scanf("%d %d",&n,&m);
    static SegmentTree *T=new SegmentTree(n);
    for(int i=1,opt;i<=m;++i)
    {
        scanf("%d",&opt);
        switch(opt)
        {
            case 1:
                T->Rank();
                break;
            case 2:
                T->Find();
                break;
            case 3:
                T->Modify();
                break;
            case 4:
                T->Prev();
                break;
            case 5:
                T->Next();
                break;
        }
        T->Print();
    }
    delete T;
    return 0;
}

谢谢阅读。

以上是关于「模板」 树套树的主要内容,如果未能解决你的问题,请参考以下文章

模板二逼平衡树(树套树)

P3380 模板二逼平衡树(树套树)

洛谷 P3380 模板二逼平衡树(树套树)

[模板] 三维偏序 - 树套树,线段树

P3380 模板二逼平衡树(树套树)

bzoj 3196 树套树模板