SP1716 GSS3 - Can you answer these queries III

Posted ehznehc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SP1716 GSS3 - Can you answer these queries III相关的知识,希望对你有一定的参考价值。

题意

序列单点修改,区间询问最大连续子段和。

最大子段和难以更新,不过这里的单点修改降低了难度,不用维护标记了。现在要做的就是通过维护数个数据支持最大子段和的查询。

考虑最大子段和是连续子段,如果在这个子段中砍一刀,它仍然是两段:

左边的子段中,紧靠右边的最大子段和
右边的子段中,紧靠左边的最大子段和

而反过来,知道了右子段中紧靠左边的最大子段和,左子段中紧靠右边的最大子段和时,就可以还原出这个最大子段。当然,这是在已知中间点(砍的一刀)的情况下。

因为最大子段还有可能在左子段中,与右子段没有公共部分。所以这时的答案就是左子段中的最大子段和。反之则同理。

如图:技术图片

这三个信息就可以拼凑出整个区间的最大子段和了。

所以维护四个信息:区间和,最大子段和,紧靠左边的最大子段和,紧靠右边的最大子段和。

紧靠左边的最大子段和,紧靠右边的最大子段需要利用区间和才可以\(O(1)\)更新。这部分很好模拟,不懂的可以看代码。

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=50005;
int n,m,a[MAXN],sum[MAXN<<2],maxs[MAXN<<2],lefts[MAXN<<2],rights[MAXN<<2];
int u,v,w;
struct data
    int _sum,_maxs,_lefts,_rights;
;

inline void upd(int x)

    sum[x]=sum[x<<1]+sum[x<<1|1];
    maxs[x]=max(max(maxs[x<<1],maxs[x<<1|1]),rights[x<<1]+lefts[x<<1|1]);
    lefts[x]=max(sum[x<<1]+lefts[x<<1|1],lefts[x<<1]);
    rights[x]=max(rights[x<<1]+sum[x<<1|1],rights[x<<1|1]);


inline void build(int x,int l,int r)

    int mid=(l+r)>>1;
    if(l==r)
    
        sum[x]=a[l];
        maxs[x]=a[l];
        lefts[x]=a[l];
        rights[x]=a[l];
        return;
    
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
    upd(x);


inline data query(int x,int l,int r,int ql,int qr)

    int mid=(l+r)>>1;
    data temp,lt,rt;
    if(ql<=l&&r<=qr) 
    
        temp._sum=sum[x];
        temp._maxs=maxs[x];
        temp._lefts=lefts[x];
        temp._rights=rights[x];
        
        return temp;
    
    if(ql<=mid) lt=query(x<<1,l,mid,ql,qr);
    if(mid<qr) rt=query(x<<1|1,mid+1,r,ql,qr);
    if(ql<=mid&&mid<qr)
    
        temp._sum=lt._sum+rt._sum;
        temp._maxs=max(lt._rights+rt._lefts,max(lt._maxs,rt._maxs));
        temp._lefts=max(lt._lefts,lt._sum+rt._lefts);
        temp._rights=max(rt._rights,lt._rights+rt._sum);
        return temp;
     else 
        if(ql<=mid) return lt;
        else return rt;
    


inline void modify(int x,int l,int r,int target,int num)

    if(l==r&&r==target)
    
        sum[x]=num;
        maxs[x]=num;
        lefts[x]=num;
        rights[x]=num;
     else 
        int mid=(l+r)>>1;
        if(target<=mid) modify(x<<1,l,mid,target,num);
        if(mid<target) modify(x<<1|1,mid+1,r,target,num);
        upd(x);
    


signed main()

    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    build(1,1,n);
    cin>>m;
    for(register int i=1;i<=m;i++)
    
        cin>>u>>v>>w;
        if(u==0) modify(1,1,n,v,w);
        if(u==1) cout<<query(1,1,n,v,w)._maxs<<"\n";
    
    return 0;

以上是关于SP1716 GSS3 - Can you answer these queries III的主要内容,如果未能解决你的问题,请参考以下文章

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III 线段树

题解 SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树