题解 CF280D 【k-Maximum Subsequence Sum】

题意:

长度为的数列,支持两种操作:

1.修改某个位置的值

2.询问区间里选出至多个不相交的
子段和的最大值。

一共有个操作

题解:线段树+堆

当k=1是答案就是最大子段和

当k=2是答案就有两种情况了:

1:最大子段和+不相交的次大子段和

2:最大子段和-最大子段和区间的最大子段和
(其实就是把最大子段和分成两部分)

我们就想到像超级钢琴一样,选出一段,就加入,

比如我们在区间中找到最大子段和,那么我们就要把,的最大子段和已以及的最小子段和加入堆中

如果是最小子段和也差不多。在区间中找到最小子段和,那么我们就要把,的最小子段和已以及的最大子段和加入堆中

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define next Next
//#define int long long
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
void write(int x)
{
    if(x<10)
    {
        putchar('0'+x);
        return;
    }
    write(x/10);
    putchar('0'+x%10);
}
#define mid (l+r)/2
const int N=1e5+5;
int n,m,opt,x,y,a[N]; 
struct node{
    int sum,ans,l,r,ansl,ansr,ql,qr;
}tree[N*4],tree2[N*4];
struct Node{
    int val,l,r,ql,qr,opt;
};
bool operator < (Node a,Node b)
{
    return a.val<b.val;
}
void pushup(int nod,int l,int r)
{
    tree[nod].sum=tree[nod*2].sum+tree[nod*2+1].sum;
    if(tree[nod*2].sum+tree[nod*2+1].l>tree[nod*2].l)
    {
        tree[nod].l=tree[nod*2].sum+tree[nod*2+1].l;
        tree[nod].qr=tree[nod*2+1].qr;
    }
    else{
        tree[nod].l=tree[nod*2].l;
        tree[nod].qr=tree[nod*2].qr;
    }
    if(tree[nod*2+1].sum+tree[nod*2].r>tree[nod*2+1].r)
    {
        tree[nod].r=tree[nod*2+1].sum+tree[nod*2].r;
        tree[nod].ql=tree[nod*2].ql;
    }
    else{
        tree[nod].r=tree[nod*2+1].r;
        tree[nod].ql=tree[nod*2+1].ql;
    }
    tree[nod].ans=tree[nod*2].ans;
    tree[nod].ansl=tree[nod*2].ansl;
    tree[nod].ansr=tree[nod*2].ansr;
    if(tree[nod*2+1].ans>tree[nod].ans)
    {
        tree[nod].ans=tree[nod*2+1].ans;
        tree[nod].ansl=tree[nod*2+1].ansl;
        tree[nod].ansr=tree[nod*2+1].ansr;    
    }
    if(tree[nod*2].r+tree[nod*2+1].l>tree[nod].ans)
    {
        tree[nod].ans=tree[nod*2].r+tree[nod*2+1].l;
        tree[nod].ansl=tree[nod*2].ql;
        tree[nod].ansr=tree[nod*2+1].qr;            
    }
}
void build(int nod,int l,int r)
{
    if(l==r)
    {
        tree[nod]=(node){a[l],a[l],a[l],a[l],l,r,l,r};
        return;
    }
    build(nod*2,l,mid);
    build(nod*2+1,mid+1,r);
    pushup(nod,l,r);
}
void change(int nod,int l,int r,int x,int y)
{
    if(l==r)
    {
        tree[nod]=(node){y,y,y,y,l,r,l,r};
        return;
    }
    if(x<=mid)change(nod*2,l,mid,x,y);
    else change(nod*2+1,mid+1,r,x,y);
    pushup(nod,l,r);
}
node find(int nod,int l,int r,int L,int R)
{
    if(l==L&&r==R)return tree[nod];
    if(R<=mid)return find(nod*2,l,mid,L,R);
    else if(L>mid)return find(nod*2+1,mid+1,r,L,R);
    node x=find(nod*2,l,mid,L,mid),y=find(nod*2+1,mid+1,r,mid+1,R),res;
    res.sum=x.sum+y.sum;
    if(x.sum+y.l>x.l)
    {
        res.l=x.sum+y.l;
        res.qr=y.qr;
    }
    else{
        res.l=x.l;
        res.qr=x.qr;
    }
    if(y.sum+x.r>y.r)
    {
        res.r=y.sum+x.r;
        res.ql=x.ql;
    }
    else{
        res.r=y.r;
        res.ql=y.ql;
    }
    res.ans=x.ans;
    res.ansl=x.ansl;
    res.ansr=x.ansr;
    if(y.ans>res.ans)
    {
        res.ans=y.ans;
        res.ansl=y.ansl;
        res.ansr=y.ansr;    
    }
    if(x.r+y.l>res.ans)
    {
        res.ans=x.r+y.l;
        res.ansl=x.ql;
        res.ansr=y.qr;            
    }
    return res;
}

void pushup2(int nod,int l,int r)
{
    tree2[nod].sum=tree2[nod*2].sum+tree2[nod*2+1].sum;
    if(tree2[nod*2].sum+tree2[nod*2+1].l>tree2[nod*2].l)
    {
        tree2[nod].l=tree2[nod*2].sum+tree2[nod*2+1].l;
        tree2[nod].qr=tree2[nod*2+1].qr;
    }
    else{
        tree2[nod].l=tree2[nod*2].l;
        tree2[nod].qr=tree2[nod*2].qr;
    }
    if(tree2[nod*2+1].sum+tree2[nod*2].r>tree2[nod*2+1].r)
    {
        tree2[nod].r=tree2[nod*2+1].sum+tree2[nod*2].r;
        tree2[nod].ql=tree2[nod*2].ql;
    }
    else{
        tree2[nod].r=tree2[nod*2+1].r;
        tree2[nod].ql=tree2[nod*2+1].ql;
    }
    tree2[nod].ans=tree2[nod*2].ans;
    tree2[nod].ansl=tree2[nod*2].ansl;
    tree2[nod].ansr=tree2[nod*2].ansr;
    if(tree2[nod*2+1].ans>tree2[nod].ans)
    {
        tree2[nod].ans=tree2[nod*2+1].ans;
        tree2[nod].ansl=tree2[nod*2+1].ansl;
        tree2[nod].ansr=tree2[nod*2+1].ansr;    
    }
    if(tree2[nod*2].r+tree2[nod*2+1].l>tree2[nod].ans)
    {
        tree2[nod].ans=tree2[nod*2].r+tree2[nod*2+1].l;
        tree2[nod].ansl=tree2[nod*2].ql;
        tree2[nod].ansr=tree2[nod*2+1].qr;            
    }
}
void build2(int nod,int l,int r)
{
    if(l==r)
    {
        tree2[nod]=(node){-a[l],-a[l],-a[l],-a[l],l,r,l,r};
        return;
    }
    build2(nod*2,l,mid);
    build2(nod*2+1,mid+1,r);
    pushup2(nod,l,r);
}
void change2(int nod,int l,int r,int x,int y)
{
    if(l==r)
    {
        tree2[nod]=(node){-y,-y,-y,-y,l,r,l,r};
        return;
    }
    if(x<=mid)change2(nod*2,l,mid,x,y);
    else change2(nod*2+1,mid+1,r,x,y);
    pushup2(nod,l,r);
}
node find2(int nod,int l,int r,int L,int R)
{
    if(l==L&&r==R)return tree2[nod];
    if(R<=mid)return find2(nod*2,l,mid,L,R);
    else if(L>mid)return find2(nod*2+1,mid+1,r,L,R);
    node x=find2(nod*2,l,mid,L,mid),y=find2(nod*2+1,mid+1,r,mid+1,R),res;
    res.sum=x.sum+y.sum;
    if(x.sum+y.l>x.l)
    {
        res.l=x.sum+y.l;
        res.qr=y.qr;
    }
    else{
        res.l=x.l;
        res.qr=x.qr;
    }
    if(y.sum+x.r>y.r)
    {
        res.r=y.sum+x.r;
        res.ql=x.ql;
    }
    else{
        res.r=y.r;
        res.ql=y.ql;
    }
    res.ans=x.ans;
    res.ansl=x.ansl;
    res.ansr=x.ansr;
    if(y.ans>res.ans)
    {
        res.ans=y.ans;
        res.ansl=y.ansl;
        res.ansr=y.ansr;    
    }
    if(x.r+y.l>res.ans)
    {
        res.ans=x.r+y.l;
        res.ansl=x.ql;
        res.ansr=y.qr;            
    }
    return res;
}
signed main()
{
//     freopen("easy.in","r",stdin);
//     freopen("easy.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    build2(1,1,n);
    m=read();
    for(int i=1;i<=m;i++)
    {
        int opt=read();
        if(opt==0)
        {
            int x=read(),y=read();
            a[x]=y;
            change(1,1,n,x,y);
            change2(1,1,n,x,y);
        }
        else{
            int l=read(),r=read(),k=read(),ma=0;
            priority_queue<Node>q;
            node xu=find(1,1,n,l,r);
            q.push((Node){xu.ans,l,r,xu.ansl,xu.ansr,1});
            for(int i=1;i<=k;i++)
            {
                Node u=q.top();q.pop();
                if(u.val<0)break;
                ma+=u.val;
                if(u.opt==1)
                {
                    node xu=find2(1,1,n,u.ql,u.qr);
                    if(xu.ans>0)
                    {
                        q.push((Node){xu.ans,u.ql,u.qr,xu.ansl,xu.ansr,0});
                    }
                    if(u.ql>u.l)
                    {
                        node xu=find(1,1,n,u.l,u.ql-1);
                        if(xu.ans>0)
                        {
                            q.push((Node){xu.ans,u.l,u.ql-1,xu.ansl,xu.ansr,1});
                        }
                    }
                    if(u.qr<u.r)
                    {
                        node xu=find(1,1,n,u.qr+1,u.r);
                        if(xu.ans>0)
                        {
                            q.push((Node){xu.ans,u.qr+1,u.r,xu.ansl,xu.ansr,1});
                        }
                    }
                }
                else{
                    node xu=find(1,1,n,u.ql,u.qr);
                    if(xu.ans>0)
                    {
                        q.push((Node){xu.ans,u.ql,u.qr,xu.ansl,xu.ansr,1});
                    }
                    if(u.ql>u.l)
                    {
                        node xu=find2(1,1,n,u.l,u.ql-1);
                        if(xu.ans>0)
                        {
                            q.push((Node){xu.ans,u.l,u.ql-1,xu.ansl,xu.ansr,0});
                        }
                    }
                    if(u.qr<u.r)
                    {
                        node xu=find2(1,1,n,u.qr+1,u.r);
                        if(xu.ans>0)
                        {
                            q.push((Node){xu.ans,u.qr+1,u.r,xu.ansl,xu.ansr,0});
                        }
                    }        
                }
                if(q.empty())break;
            }
            write(ma);
            putchar('\n');
        }
    }
    return 0;
}
/*
15
-4 8 -3 -10 10 4 -7 -7 0 -6 3 8 -10 7 2
1
1 3 9 2
*/