• Luogu P2042 [NOI2005]维护数列(平衡树)


    P2042 [NOI2005]维护数列

    题意

    题目描述

    请写一个程序,要求维护一个数列,支持以下(6)种操作:(请注意,格式栏中的下划线‘_’表示实际输入文件中的空格)

    P2042

    输入输出格式

    输入格式:

    输入文件的第(1)行包含两个数(N)(M)(N)表示初始时数列中数的个数,(M)表示要进行的操作数目。 第(2)行包含(N)个数字,描述初始时的数列。以下(M)行,每行一条命令,格式参见问题描述中的表格。

    输出格式:

    对于输入数据中的GET-SUMMAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

    输入输出样例

    输入样例#1:

    9 8
    2 -6 3 5 1 -5 -3 6 3
    GET-SUM 5 4
    MAX-SUM
    INSERT 8 3 -5 7 2
    DELETE 12 1
    MAKE-SAME 3 3 2
    REVERSE 3 6
    GET-SUM 5 4
    MAX-SUM
    

    输出样例#1:

    -1
    10
    1
    10
    

    说明

    你可以认为在任何时刻,数列中至少有(1)个数。

    输入数据一定是正确的,即指定位置的数在数列中一定存在。

    (50\%)的数据中,任何时刻数列中最多含有(30000)个数;

    (100\%)的数据中,任何时刻数列中最多含有(500000)个数。

    (100\%)的数据中,任何时刻数列中任何一个数字均在([-1000,1000])内。

    (100\%)的数据中,(Mleq 20000),插入的数字总数不超过(4000000)

    思路

    平衡树板子题(其实没有那么板),调试的难度还是很大的。

    (fhq Treap)的线性建树是我从这题学到的新定西,直接放代码吧:

    int build(int now)//新加入的点的数量
    {
        stack<int>S;//主要思想是维护一个单调栈
        int last;
        for(int i=1;i<=now;i++)
        {
            int x=new_node(a[i]);last=0;//新建结点
            while(!S.empty()&&rnd(S.top())>rnd(x)) last=S.top(),update(S.top()),S.pop();//维护小根堆,寻找新结点的父节点
            if(!S.empty()) rs(S.top())=x;
            ls(x)=last,S.push(x);//把刚刚弹出的结点再接上
        }
        while(!S.empty()) last=S.top(),update(S.top()),S.pop();
        return last;//返回新建树的根
    }
    

    本题的第二个难点是内存回收,可以直接开一个队列记录被删除的点,新建结点时从队列中取就好了。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=5e5+5;
    int n,m,rt,cnt,a[MAXN];
    bool H[MAXN];
    int read()
    {
        bool f=true;int re=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=false;ch=getchar();}
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return f?re:-re;
    }
    struct Node
    {
        int ls,rs,sz,val,rnd,sum;
        int sub_sum,left_sub_sum,right_sub_sum;
        int change_tag;
        bool reverse_tag;
        #define ls(a) node[a].ls
        #define rs(a) node[a].rs
        #define sz(a) node[a].sz
        #define val(a) node[a].val
        #define rnd(a) node[a].rnd
        #define sum(a) node[a].sum
        #define lsm(a) node[a].left_sub_sum
        #define rsm(a) node[a].right_sub_sum
        #define sub(a) node[a].sub_sum
        #define ctg(a) node[a].change_tag
        #define rtg(a) node[a].reverse_tag
    }node[MAXN];
    queue<int>dustbin;
    int new_node(int k)
    {
        int re;
        if(!dustbin.empty()) re=dustbin.front(),H[dustbin.front()]=false,dustbin.pop();
        else re=++cnt;
        ls(re)=rs(re)=0,sz(re)=1;
        val(re)=sum(re)=sub(re)=k;
        lsm(re)=rsm(re)=max(k,0);
        rnd(re)=rand();
        ctg(re)=INT_MAX,rtg(re)=false;
        return re;
    }
    void update(int now)
    {
        if(ls(now)&&rs(now))
        {
            sz(now)=sz(ls(now))+sz(rs(now))+1;
            sum(now)=sum(ls(now))+sum(rs(now))+val(now);
            lsm(now)=max(lsm(ls(now)),sum(ls(now))+val(now)+lsm(rs(now)));
            rsm(now)=max(rsm(rs(now)),sum(rs(now))+val(now)+rsm(ls(now)));
            sub(now)=max(max(sub(ls(now)),sub(rs(now))),rsm(ls(now))+val(now)+lsm(rs(now)));
        }
        else if(ls(now))
        {
            sz(now)=sz(ls(now))+1;
            sum(now)=sum(ls(now))+val(now);
            lsm(now)=max(max(lsm(ls(now)),sum(ls(now))+val(now)),0);
            rsm(now)=max(0,val(now)+rsm(ls(now)));
            sub(now)=max(sub(ls(now)),rsm(ls(now))+val(now));
        }
        else if(rs(now))
        {
            sz(now)=sz(rs(now))+1;
            sum(now)=sum(rs(now))+val(now);
            rsm(now)=max(max(rsm(rs(now)),sum(rs(now))+val(now)),0);
            lsm(now)=max(0,val(now)+lsm(rs(now)));
            sub(now)=max(sub(rs(now)),lsm(rs(now))+val(now));
        }
        else
        {
            sz(now)=1,sum(now)=sub(now)=val(now);
            lsm(now)=rsm(now)=max(val(now),0);
        }
    }
    void pushdown(int now)
    {
        if(rtg(now))
        {
            if(ls(now))
            {
                swap(ls(ls(now)),rs(ls(now)));
                swap(lsm(ls(now)),rsm(ls(now)));
                rtg(ls(now))^=1;
            }
            if(rs(now))
            {
                swap(ls(rs(now)),rs(rs(now)));
                swap(lsm(rs(now)),rsm(rs(now)));
                rtg(rs(now))^=1;
            }
        }
        if(ctg(now)!=INT_MAX)
        {
            if(ls(now))
            {
                sum(ls(now))=sz(ls(now))*ctg(now);
                val(ls(now))=ctg(now);
                lsm(ls(now))=rsm(ls(now))=max(sum(ls(now)),0);
                sub(ls(now))=max(val(ls(now)),sum(ls(now)));
                ctg(ls(now))=ctg(now);
            }
            if(rs(now))
            {
                sum(rs(now))=sz(rs(now))*ctg(now);
                val(rs(now))=ctg(now);
                lsm(rs(now))=rsm(rs(now))=max(sum(rs(now)),0);
                sub(rs(now))=max(val(rs(now)),sum(rs(now)));
                ctg(rs(now))=ctg(now);
            }
        }
        rtg(now)=false,ctg(now)=INT_MAX;
    }
    int merge(int x,int y)
    {
        if(x) pushdown(x);
        if(y) pushdown(y);
        if(!x||!y) return x+y;
        if(rnd(x)<rnd(y))
        {
            rs(x)=merge(rs(x),y);
            update(x);
            return x;
        }
        else
        {
            ls(y)=merge(x,ls(y));
            update(y);
            return y;
        }
    }
    void split(int now,int k,int &x,int &y)
    {
        if(!now) x=y=0;
        else
        {
            pushdown(now);
            if(sz(ls(now))>=k)
            {
                y=now;
                split(ls(y),k,x,ls(y));
            }
            else
            {
                x=now;
                split(rs(x),k-sz(ls(now))-1,rs(x),y);
            }
            update(now);
        }
    }
    void recycle(int now)
    {
        if(!H[now]) dustbin.push(now),H[now]=false;
        if(ls(now)) recycle(ls(now));
        if(rs(now)) recycle(rs(now));
    }
    int build(int now)
    {
        stack<int>S;
        int last;
        for(int i=1;i<=now;i++)
        {
            int x=new_node(a[i]);last=0;
            while(!S.empty()&&rnd(S.top())>rnd(x)) last=S.top(),update(S.top()),S.pop();
            if(!S.empty()) rs(S.top())=x;
            ls(x)=last,S.push(x);
        }
        while(!S.empty()) last=S.top(),update(S.top()),S.pop();
        return last;
    }
    int main()
    {
        srand(19260817);
        n=read(),m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        rt=build(n);
        while(m--)
        {
            char opt[20];
            scanf("%s",opt);
            if(opt[0]=='I')
            {
                int x,y,p,t;
                p=read(),t=read();
                split(rt,p,x,y);
                for(int i=1;i<=t;i++) a[i]=read();
                rt=merge(merge(x,build(t)),y);
            }
            else if(opt[0]=='D')
            {
                int x,y,z,p,t;
                p=read(),t=read();
                split(rt,p-1,x,y);
                split(y,t,y,z);
                recycle(y);
                rt=merge(x,z);
            }
            else if(opt[0]=='R')
            {
                int x,y,z,p,t;
                p=read(),t=read();
                split(rt,p-1,x,y);
                split(y,t,y,z);
                swap(ls(y),rs(y));
                swap(lsm(y),rsm(y));
                rtg(y)^=1;
                rt=merge(merge(x,y),z);
            }
            else if(opt[0]=='G')
            {
                int x,y,z,p,t;
                p=read(),t=read();
                split(rt,p-1,x,y);
                split(y,t,y,z);
                printf("%d
    ",sum(y));
                rt=merge(merge(x,y),z);
            }
            else if(opt[0]=='M')
            {
                if(opt[2]=='K')
                {
                    int x,y,z,p,t,tmp;
                    p=read(),t=read(),tmp=read();
                    split(rt,p-1,x,y);
                    split(y,t,y,z);
                    ctg(y)=val(y)=tmp,sum(y)=sz(y)*ctg(y);
                    lsm(y)=rsm(y)=sub(y)=max(val(y),sum(y));
                    rt=merge(merge(x,y),z);
                }
                else if(opt[2]=='X') printf("%d
    ",sub(rt));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    用户使用调查报告
    Beta阶段敏捷冲刺五
    Beta阶段敏捷冲刺四
    Beta阶段敏捷冲刺三
    Beta阶段敏捷冲刺二
    Beta阶段敏捷冲刺一
    软工网络15团队作业8——Beta阶段敏捷冲刺
    Beta阶段Scrum 冲刺博客合集
    软工网络15Alpha阶段敏捷冲刺博客集合
    项目复审——Beta阶段
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9903963.html
Copyright © 2020-2023  润新知