首页 > 代码库 > 51nod1049(最大子段和2)

51nod1049(最大子段和2)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1049

 

题意:中文题诶~

 

思路:本题和51nod1049(题解)类似,不同的是本题的数列是一个环;

我们可以这样想,取得最大和的子段有两种情况:

 1.从第i个元素到第j个元素,i<=j; 

 2.从第i个元素到第j个元素,i>j;

第1种情况和1049那题是一样的;

第2种情况我们可以反过来想,所有元素的总和是固定的,若 i~j 能取到最大值,那么 j~i 的和为最小子段和,我们可以用和 1 中类似的方法求出最小子段和,再用所有元素的和减去它就能得到最大值啦;

两种情况取得的最大值中较大着即为答案;

 

代码:

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 const int MAXN=1e5+10;
 6 ll a[MAXN], b[MAXN], c[MAXN];
 7 
 8 ll min(ll a, ll b){
 9     return a>b?b:a;
10 }
11 
12 ll max(ll a, ll b){
13     return a>b?a:b;
14 }
15 
16 int main(void){
17     ll n, ans=0, mm=0, mn=0, x, num=0, cnt=0;
18     cin >> n;
19     for(int i=1; i<=n; i++){
20         cin >> x;
21         ans+=x;
22         a[i]=ans;
23         if(ans>mm){
24             b[i]=ans;
25             mm=ans;
26         }else{
27             b[i]=b[i-1];
28         }
29         if(ans<mn){
30             c[i]=ans;
31             mn=ans;
32         }else{
33             c[i]=c[i-1];
34         }
35     }
36     cout << endl;
37     for(int i=1; i<=n; i++){
38         num=min(num, a[i]-b[i-1]);
39         cnt=max(cnt, a[i]-c[i-1]);
40     }
41     ans=ans-num;
42     cout << (ans>cnt?ans:cnt) << endl;
43     return 0;
44 }

 

51nod1049(最大子段和2)