循环数组最大子段和 (dp)

来源:互联网 发布:java福利院管理系统 编辑:程序博客网 时间:2024/06/05 14:01
N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1n−1,ann,a11,a22这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数 (-10^9 <= Sii <= 10^9)
Output
输出循环数组的最大子段和。
Sample Input
6
-2
11
-4
13
-5
-2
Sample Output

20


如果最大和在不循环的情况下得到,我们可以按照最大的连续子序列和的方法找到一个最大的和maxSum;如果最大和的在循环的情况下得到,我们我们可以求一个最小连续子序列的和minSum,用数组总和tot-minSum就是在循环的情况下最大和;最终答案取两者最大值ans = max{minSum,tot-maxSum}

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <set>#include <stack>#include <queue>#include <vector>#include <cctype>using namespace std;#define CL(a) memset(a,0,sizeof(a));#define LL long longconst int INF= 0x7fffffff;const int maxn = 1e6 + 100;LL a[maxn];int main(){    int n;LL maxSum,minSum,ans,sum,tot;    while (scanf("%d",&n) != EOF){        tot = 0;        for (int i = 0;i < n;i++){            scanf("%lld",&a[i]);            tot += a[i];        }        maxSum = sum = 0;        minSum = INF;        for (int i = 0;i < n;i++){            sum = max(sum + a[i],0ll);            maxSum = max(maxSum,sum);        }        for (int i = 0;i < n;i++){            sum = min(sum + a[i],0ll);            minSum = min(minSum,sum);        }        ans = max(maxSum,tot - minSum);        printf("%lld\n",ans);    }    return 0;}

取反也可以:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<queue>#include<map>#include<set>#include<vector>#include<string>#include<stack>#include<cstdlib>typedef long long ll;using namespace std;ll a[50050],dp[55000];int main(){    int n,flag=0;    ll ans1=0,ans2=0,sum=0,t=0;    cin>>n;    int r;    for(r=1;r<=n;r++){        scanf("%lld",&a[r]);        t+=a[r];        if(a[r]>=0)flag=1;    }    if(!flag){        printf("0\n");        return 0;    }    else{        for(int i=1;i<=n;i++){            sum=max(sum,0ll)+a[i];            ans1=max(ans1,sum);        }        sum=0;        for(int i=1;i<=n;i++){            a[i]=-a[i];            sum=max(sum,0ll)+a[i];            ans2=max(ans2,sum);        }        printf("%I64d\n",max(ans1,t+ans2));    }    return 0;}


原创粉丝点击