51nod 循环数组最大子段和

这个问题就是在原来的基础上加上了可以循环。

那么我们可以分两种情况处理,一种是有从尾到头的,例如1表示取,0表示不取,则是11000011

一种是没有跨越的, 即000111100

那么对于第二种情况可以直接用最大字段和做,关键是第一段要怎么处理。

这里需要用到逆向思维,在1110000111这一个答案中,0000是最小字段和,因为总和是一定的 。

那么我们就可以用类似的方法算出最小字段和,然后用总和一减就ok了。

最后两种情况取max就是答案。

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;

typedef long long ll;
const int MAXN = 51234;
int a[MAXN], n;
ll ans, sum, ans1, ans2;

int main()
{
	scanf("%d", &n);
	REP(i, 0, n) scanf("%d", &a[i]), sum += a[i];
	ll t = 0;
	REP(i, 0, n) t = min((ll)a[i], t + a[i]), ans = min(ans, t);
	ans1 = sum - ans;
	t = 0;
        REP(i, 0, n) t = max((ll)a[i], t + a[i]), ans2 = max(ans2, t);
	printf("%lld\n", max(ans1, ans2));
	return 0;	
} 

 

posted @ 2018-08-18 12:13  Sugewud  阅读(99)  评论(0编辑  收藏  举报