最大连续和---变种版

问题: 最大和子序列。

问题描述
给一个整数数组A={a1,a2,…an},将这个数组首位连成一个环装,它的一个子序列是指这个数组连续的一段,比如a2,a3,…,ak, ai。请从这个环上选取两个不重叠的非空子序列,使这两个子序列中的所有数字之和最大。
在三个样例中分别选取的子序列是:
样例一:{a1} {a3}
样例二:{a1} {a3}
样例三:{a5,a1} {a3}

输入:
输入的第一行包含一个正整数(1<=T<=40),表示有T组测试数据。
接下来每个测试数据包含两行,第一行是一个正整数n(2<=n<=50000),
第二行是一个空格隔开的数组A的n个数,依次为a1,a2,…,an(|ai|<=10000)。

输出
每组数据输出一行,包含一个数,即所求的这两个子序列的元素之和。

Sample Input
3
3
1 -1 0
4
1 -1 1 -1
5
1 -1 1 -1 1

Sample Output
1
2
3

#include <stdio.h>

#define INF 100000000
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)

int a[50010];
int hmax[50010],tmax[50010],hmin[50010],tmin[50010];

int main()
{
    int cas;
    // 输入总的序列数
    scanf("%d",&cas);
    while(cas--)
    {
        int i,n,t,sum,ans,maxNum;
        // 输入序列中数的个数
        scanf("%d",&n);
        sum = 0;
        maxNum = -INF;
        //input a new element and calculate  
        for(i=1; i<=n; ++i)
        {
            scanf("%d",&a[i]);
            if(maxNum<a[i])  // cal max num
                maxNum = a[i];
            sum += a[i];  //cal sum, in order to deal with the circle cal 
        }
        t = 0;
        for(i=0; i<=n; i++) // cal 最大连续和  from head
        {
            hmax[0] = -INF;
            t += a[i];
            hmax[i] = max(hmax[i-1],t); // i number' max contigious sumfrom :1
            if(t<0)
                t = 0;
        }
        t = 0;
        tmax[n+1] = -INF;
        for(i=n; i>=1; --i) // cal 最大连续和 from tail
        {
            t += a[i];
            tmax[i] = max(tmax[i+1],t);
            if(t<0) 
                t = 0;
        }
        t = 0;
        hmin[0] = INF;
        for(i=1; i<=n; ++i) // cal最小连续和 from head
        {
            t += a[i];
            hmin[i] = min(hmin[i-1],t);
            if(t>0) t=0;  
        }
        t=0;  
        tmin[n+1]=INF;  
        for(i=n;i>=1;--i)//cal 最小连续和 from tail  
        {  
            t+=a[i];  
            tmin[i]=min(tmin[i+1],t);  
            if(t>0) t=0;  
        }  

        ans = -INF;
        for(i=1; i<n; i++) // cal the ans without circle
        {
            if(ans < hmax[i]+tmax[i])
                ans = hmax[i]+tmax[i];
        }
        for(i=1; i<n; i++) // deal with the circle
        {
            t = sum-(hmin[i]+tmin[i+1]);
            //hmin[i]+tmin[i+1] must be nagative, or part of them must can be added into hmax or tmax
            if(t!=0 && ans<t)
                ans = t;
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值