51nod 1050 循环数组最大子段和

来源:互联网 发布:喜剧总动员 知乎 编辑:程序博客网 时间:2024/05/09 02:09

题目链接:

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050

题解:

本题的思路主要分为两个方向:

1.就是正常的思路的时候,直接去求解最大子列和就行。

2.当最大的值出现的是收尾相连的时候的情况,这种时候,我们可以这么想:

出现这种情况的主要的原因就是,中的那段比较的小,导致了最大的值出现在了首尾,所以,换下思路,就是说将所有的值取反了以后,中间会出现最大值,而不是在首尾。

所以,综上,我们先计算总的和ans,在计算最大值的和ans1,然后讲数列进行取反操作,在进行取最大值ans2,然后再进行max(ans1,ans+ans2)(注:这里的ans2会将ans中的值抵消掉,直接剩下最大值)

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const ll  maxn = 50000+10;#define met(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3fll  num[maxn];int main(){    ll  n;    while(cin>>n)    {        ll  ans=0,ans1=0,ans2=0;        for(ll  i=0;i<n;i++)        {            cin>>num[i];            ans+=num[i];        }        ll  sum1=0,sum2=0;        for(ll  i=0;i<n;i++)        {            sum1+=num[i];            if(sum1>=ans1)                ans1=sum1;            if(sum1<0)                sum1=0;        }        for(ll  i=0;i<n;i++)            num[i]*=(-1);        for(ll  i=0;i<n;i++)        {            sum2+=num[i];            if(sum2>=ans2)                ans2=sum2;            if(sum2<0)                sum2=0;        }        cout<<max(ans1,ans+ans2)<<endl;    }}


0 0