P2042 [NOI2005] 维护数列

P2042 [NOI2005] 维护数列

请写一个程序,要求维护一个数列,支持以下 \(6\) 种操作:

编号 名称 格式 说明
1 插入 \(\operatorname{INSERT}\ posi \ tot \ c_1 \ c_2 \cdots c_{tot}\) 在当前数列的第 \(posi\) 个数字后插入 \(tot\) 个数字:\(c_1, c_2 \cdots c_{tot}\);若在数列首插入,则 \(posi\)\(0\)
2 删除 \(\operatorname{DELETE} \ posi \ tot\) 从当前数列的第 \(posi\) 个数字开始连续删除 \(tot\) 个数字
3 修改 \(\operatorname{MAKE-SAME} \ posi \ tot \ c\) 从当前数列的第 \(posi\) 个数字开始的连续 \(tot\) 个数字统一修改为 \(c\)
4 翻转 \(\operatorname{REVERSE} \ posi \ tot\) 取出从当前数列的第 \(posi\) 个数字开始的 \(tot\) 个数字,翻转后放入原来的位置
5 求和 \(\operatorname{GET-SUM} \ posi \ tot\) 计算从当前数列的第 \(posi\) 个数字开始的 \(tot\) 个数字的和并输出
6 求最大子列和 \(\operatorname{MAX-SUM}\) 求出当前数列中和最大的一段子列,并输出最大和

数据规模与约定

  • 对于 \(100\%\) 的数据,任何时刻数列中最多含有 \(5 \times 10^5\) 个数,任何时刻数列中任何一个数字均在 \([-10^3, 10^3]\) 内,\(1 \le M \le 2 \times 10^4\),插入的数字总数不超过 \(4 \times 10^6\)

Solution:

如果没有最大子段和的话那么这题就是一个普通的平衡树板子,但是有了这个诡异的最大字段和我们就需要在pushup的时候尤为小心

这就是你一道紫题写一个早上的理由?(╯°Д°)╯︵ ┻━┻

由于这题我们要用平衡树维护最大子段和,所以我们需要在 pushup 时加上当前节点的贡献 \(t[x].val\) 同时,如果想写得省事一点,\(lmx,rmx\) 就不能定义为强制取左/右端点时的区间最大,而是不强制取左/右端点的区间最大。其最小值为 \(0\) (可以不取)。只有区间最大字段和 \(mx\) 需要强制取。

然后这题按题意维护平衡树即可。

还有就是这题虽然最多只有 \(5*10^5\) 个数同时在线,但是历史可能有 \(4*10^6\) 个数,所以我们需要将那些被用过的闲置空间放到 【数据删除】 上回收一下

然后这题就愉快(存疑)的做完了

Code:

#include<bits/stdc++.h>
const int N=5e5+5;
using namespace std;
inline int Max(int x,int y){return x>y ? x : y;}
int n,m,rt,cnt;
queue<int> Q;
int A[N];
//FHQ_Treap:
struct Tree{
    int ls,rs,val,lmx,rmx,mx,sum,tag,rev,siz,pri;
}t[N];
inline int rd(){return rand()*rand()+17;}
inline int Node(int val){int res=Q.front();Q.pop();t[res]={0,0,val,Max(0,val),Max(0,val),val,val,N,0,1,rd()};return res;}
int flag=0;
inline void pushup(int x)
{
    int ls=t[x].ls,rs=t[x].rs;

    t[x].siz=t[ls].siz+t[rs].siz+1;
    t[x].sum=t[ls].sum+t[rs].sum+t[x].val;
    t[x].lmx=Max(Max(t[ls].lmx,t[ls].sum+t[rs].lmx+t[x].val),0);
    t[x].rmx=Max(Max(t[rs].rmx,t[rs].sum+t[ls].rmx+t[x].val),0);
    t[x].mx=Max(t[ls].rmx+t[rs].lmx,0)+t[x].val;
    if(ls)t[x].mx=Max(t[x].mx,t[ls].mx);
    if(rs)t[x].mx=Max(t[x].mx,t[rs].mx);
}
inline void rev(int x)
{
    swap(t[x].lmx,t[x].rmx);
    t[x].rev^=1;swap(t[x].ls,t[x].rs);
}
inline void change(int x,int tag)
{
    t[x].sum=t[x].siz*tag;
    t[x].lmx=t[x].rmx=max(0,t[x].sum);
    t[x].mx=max(t[x].sum,tag);
    t[x].val=t[x].tag=tag;
}
inline void pushdown(int x)
{
    int ls=t[x].ls,rs=t[x].rs,tag=t[x].tag;
    if(t[x].rev)
    {
        if(ls)rev(ls);
        if(rs)rev(rs);
        t[x].rev=0;
    }
    if(t[x].tag!=N)
    {
        if(ls)change(ls,tag);
        if(rs)change(rs,tag);
        t[x].tag=N;
    }
    return ;
}
inline void splite(int x,int &a,int &b,int k)
{
    if(!x){a=b=0;return ;}
    int tmp=t[t[x].ls].siz+1;
    pushdown(x);
    if(k>=tmp){a=x;splite(t[x].rs,t[x].rs,b,k-tmp);}
    else {b=x;splite(t[x].ls,a,t[x].ls,k);}
    pushup(x);
}
inline int merge(int x,int y)
{
    if(!x||!y)return x|y;
    pushdown(x);pushdown(y);
    if(t[x].pri<t[y].pri){t[x].rs=merge(t[x].rs,y);pushup(x);return x;}
    else {t[y].ls=merge(x,t[y].ls);pushup(y);return y;}
}
void insert(int pos)
{
    int a,b;
    splite(rt,a,b,pos);
    for(int i=1;i<=A[0];i++)
    {
        a=merge(a,Node(A[i]));
    }
    rt=merge(a,b);
    A[0]=0;
}
inline void recycle(int x){if(!x)return ;Q.push(x);recycle(t[x].ls);recycle(t[x].rs);}
void del(int x,int tot)
{
    int a,b,c;
    splite(rt,a,b,x-1);
    splite(b,b,c,tot);
    recycle(b);
    rt=merge(a,c);
}
void same(int x,int tot,int tag)
{
    int a,b,c;
    splite(rt,a,b,x-1);
    splite(b,b,c,tot);
    change(b,tag);
    rt=merge(merge(a,b),c);
}
void reverse(int x,int tot)
{
    int a,b,c;
    splite(rt,a,b,x-1);
    splite(b,b,c,tot);
    rev(b);
    rt=merge(merge(a,b),c);
}
void sum(int x,int tot)
{
    int a,b,c;
    splite(rt,a,b,x-1);
    splite(b,b,c,tot);
    printf("%d\n",t[b].sum);
    rt=merge(merge(a,b),c);
}
char s[N];
void work()
{
    cin>>n>>m;
    for(int i=N-1;i;i--)Q.push(i);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A[++A[0]]);
    }
    insert(0);
    int pos,tot,tag;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if(s[0]=='M'&&s[2]=='X')
        {
            printf("%d\n",t[rt].mx);continue;
        }
        scanf("%d%d",&pos,&tot);
        if(s[0]=='I')
        {
            for(int i=1;i<=tot;i++)scanf("%d",&A[++A[0]]);
            insert(pos);continue;
        }
        if(s[0]=='D')
        {
            del(pos,tot);
        }
        if(s[0]=='M')
        {
            scanf("%d",&tag);
            same(pos,tot,tag);
        }
        if(s[0]=='R')
        {
            reverse(pos,tot);
        }
        if(s[0]=='G')
        {
            sum(pos,tot);
        }
    }
}
int main()
{
    srand(998244353);
    //freopen("P2042_2.in","r",stdin);freopen("P2042.out","w",stdout);
    work();
    return 0;
}
posted @ 2025-01-16 18:41  liuboom  阅读(20)  评论(0)    收藏  举报