和求最大的子段和有点像,但是是循环数组,首先我们知道如果不循环 那么就和求最大字段和一样,也就是说此子段的起点是小于终点的, 如果是循环数组那么我们可以知道此时可以是子段的起点大于重点,那么对于中间的一段显然是最小的子段和,
大体就是分情况讨论
第一种:子段的起点小于终点
第二种:子段的终点小于起点,此时起点和终点的部分就是最小的子段和
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int qq = 50000+10;
ll dp[qq];
int main(){
int n;scanf("%d",&n);
ll sum = 0;
for(int i=0; i<n; ++i) scanf("%lld",dp+i),sum+=dp[i];
ll maxn = 0, tot = 0;
for(int i=0; i<n; ++i){
tot+=dp[i];
maxn = max(maxn, tot);
if(tot<0) tot = 0;
}
tot = 0;
ll minx = 1e9+10;
for(int i=0; i<n; ++i){
tot+=dp[i];
minx = min(minx, tot);
if(tot>0) tot = 0;
}
printf("%lld\n", max(maxn, sum-minx));
return 0;
}
如果题目分析后可以分情况讨论,自己要意识到