poj 2479 Maximum sum

来源:互联网 发布:mac os 破解 编辑:程序博客网 时间:2024/04/30 13:55

题目意思不再重复,先解决一个最长段的问题,从头开始累加,加一次更新一次最大值,当sum<0时,从下一个数字开始累加。

现在解决两个段的问题,和最大的两个子段(A,B),要么都跟最长段(T)没有交集,要么把最长段一分为二。

简单证明下:如果跟最长短相交的话,那么设相交的为A,那么设A减去A和T的交集的字段和为sum

如果sum<0  那么把这段去掉能得到更优的解

如果sum>0  那么把这段加到T上面能得到更大的连续子段,矛盾。

证毕。 


#include <iostream>

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=5e4+9;
int n;
int a[maxn];


int cal(int s,int t,int &st,int &ed,int tmp)
{
    int ret=-11111,sum=0,_st=1;
    for(int i=s;i<=t;i++)
    {
        sum+=a[i]*tmp;
        if(sum>ret)
        {
            ret=sum;
            st=_st;
            ed=i;
        }
        if(sum<0)
        {
            _st=i+1;
            sum=0;
        }
    }
    return(ret);
}


int main()
{
    int T;
    for(scanf("%d",&T);T>=1;T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        int st,ed,tt;
        int ans=cal(1,n,st,ed,1);
        int ret=max(cal(1,st-1,tt,tt,1),cal(ed+1,n,tt,tt,1));
        int _ret=max(0,cal(st,ed,tt,tt,-1));
        if(ed-st>=1)
        ans+=max(ret,_ret);
        else
        ans+=ret;
        printf("%d\n",ans);
    }
    return 0;
}
原创粉丝点击