「模板」 树套树

「模板」 树套树

<题目链接>



线段树套 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;
}

谢谢阅读。

原文地址:https://www.cnblogs.com/Capella/p/9092486.html

时间: 2024-11-08 21:44:05

「模板」 树套树的相关文章

「luogu3380」【模板】二逼平衡树(树套树)

「luogu3380」[模板]二逼平衡树(树套树) 传送门 我写的树套树--线段树套平衡树. 线段树上的每一个节点都是一棵 \(\text{FHQ Treap}\) ,然后我们就可以根据平衡树的基本操作以及线段树上区间信息可合并的性质来实现了,具体细节看代码都懂. 参考代码: #include <algorithm> #include <cstdlib> #include <cstdio> #define rg register #define file(x) freo

「模板」 线段树——区间乘 &amp;&amp; 区间加 &amp;&amp; 区间求和

「模板」 线段树--区间乘 && 区间加 && 区间求和 <题目链接> 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long long p; class SegmentTree { private: struct Node { int l,r; long long v,mul,add; Node *c[2]; Node(int l,int r):l(l),r(r),mul(1LL),add(0LL) { c[

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

洛谷 P3380 [模板]二逼平衡树(树套树) 线段树套treap: 就是线段树每个节点放一个treap.建树复杂度应该是$n log n$,操作1,3,4,5的复杂度是$(log n)^2$,操作2的复杂度是$(log n)^3$. 操作3:找到线段树的对应叶子节点后找到要删除的值,在回溯的时候更新线段树相关的每一个节点(在treap中去掉要删除的值,再加入要加入的值) 操作1:将操作转化为统计(这个区间[l,r]内小于x的数的个数)+1.那么通过线段树将区间分解,然后对分解出的每一个区间对应

[BZOJ3110] [Zjoi2013] K大数查询 (树套树)

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT [

bzoj 1901: Zju2112 Dynamic Rankings(树套树)

1901: Zju2112 Dynamic Rankings 经典的带修改求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,而且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过不了. 思路很简单,用线段树维护区间,用splay维护区间内的权值,然后询问的时候,二分答案key,然后在区间内找小于key的数有多少个. 贴上模板: #include<stdio.h> #include<string.h> #include<algorithm> #def

树套树乱讲

树套树乱讲 树状数组套线段树 先学会主席树. 主席树可以被理解为一个二维平面,其中n棵树可以视作横轴,每棵树中的坐标范围(也就是线段树的坐标范围)可以视作纵轴.这样一来就是用主席树维护了一些在二维平面上的点,给定\(a,b,c,d\),可以在\(O(\log{n})\)的时间内求出满足\(a\le x_i\le b,c\le y_i\le d\)的\(i\)的数量. 而树状数组套线段树就是把这个问题动态化. 对于上述的问题,我们是通过对主席树直接维护前缀和,查询时两棵主席树相减,再在区间\([c

树套树初探

最近学了学树套树,做了几道模板题. 发现好像有点水 咳咳咳. 树套树,顾名思义,一个树套一个树.比如树状数组套平衡树,就是把树状数组的每一个结点作为一颗平衡树,线段树套权值线段树,就是一颗线段树,每一个结点都是一颗权值线段树... 如果有一个问题是要求一个区间\([l,r]\)中比\(x\)小的数有多少个带单点修改\(n<=50000\),可以用树状数组套平衡树解决,首先在每个点上建立平衡树,然后再拿树状数组维护起来,然后我们可以先求出区间\([1,r]\)中有多少个比\(x\)小的数减去区间\

知识点 - 线段树 权值 树套树 二维 可持续

知识点 - 线段树 权值 树套树 二维 可持续 //区间更新求和 inline int ls(int p) { return p << 1; }//左儿子 inline int rs(int p) { return p << 1 | 1; }//右儿子 void push_up(int p) { t[p] = t[ls(p)] + t[rs(p)]; }// 向上不断维护区间操作 void build(ll p, ll l, ll r) { if (l == r) { t[p] =

BZOJ_3196_二逼平衡树(树套树:线段树+Treap)

描述 可以处理区间问题的平衡树. 分析 树套树.可以用线段树套Treap.人生第一道树套树的题... op1:如果在整区间,直接在该区间的treap上求解.否则分两个区间求解,然后相加.最后+1. op2:这个不太好直接做,可以二分,每次假定一个值,用这个值去做op1,以此求得一个rank=k+1的数,求rank=k的数等价与求这个数的前驱pre. op3:先删后加. op4&op5:如果在整区间,直接在该区间的treap上求解,否则分量个区间求解,pre取最大值,suc取最小值.注意有些数在有