51 nod 1049 最大子段和
第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数 (-10^9 <= S[i] <= 10^9)
输出循环数组的最大子段和。
6 -2 11 -4 13 -5 -2
20
分析:本题与普通的最大子段和问题不同的是,最大子段和可以是首尾相接的情况,即可以循环。那么这个题目的最
大子段和有两种情况
(1)正常数组中间的某一段和最大。这个可以通过普通的最大子段和问题求出。
(2)此数组首尾相接的某一段和最大。这种情况是由于数组中间某段和为负值,且绝对值很大导致的,那么我
们只需要把中间的和为负值且绝对值最大的这一段序列求出,用总的和减去它就行了。
即,先对原数组求最大子段和,得到max1,然后把数组中所有元素符号取反,再求最大子段和,得到max2,
原数组的所有元素和为sum1,那么最终答案就是 max(max1,sum1+max2);
#include<iostream>
using namespace std;
int a[50005];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
long long max1,sum1,sum2,max2,sum;
max1=0;
sum1=0;sum2=0;sum=0;max2=0;
//对整个数组求和sum1
for(int i=0;i<n;i++)
sum1=sum1+a[i];
//求原数组最大字段和max1
for(int i=0;i<n;i++)
{sum=sum+a[i];
if(sum<0)
sum=0;
max1=max1>sum?max1:sum;
}
//对数组去反
for(int i=0;i<n;i++)
a[i]=-a[i];
//求去反之后最大字段和max2
for(int i=0;i<n;i++)
{ sum2=sum2+a[i];
if(sum2<0)
sum2=0;
max2=max2>sum2?max2:sum2;
}
sum=max(max1,sum1+max2);
cout<<sum;
}

浙公网安备 33010602011771号