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 }
我就是我,颜色不一样的烟火 --- geloutingyu