蚂蚁的难题(二) && 首尾相连数组的最大子数组和(nyoj 745 && nyoj 983)

这两题是一个意思,都是环形的最大子段和,把数组范围改一下,同样的代码就能过。

通常想到的办法是将数组扩大一倍,然后求n个n长度的最大子段和,然后再取一个最大值,但是这两题数据量都很大,两重for循环会超时。

其实,与线性的相比,环形的就是多了一步:求首位相连的串的最大子段和,这个怎么求?可以通过求首尾不相连的串的最小字段和min,然后把所有数字的总和减去min,就是首尾相连的串的最大子段和,其实就是,所有数字总和 - 线性的串的最小子段和 = 环形的串的最大子段和。

环形的串的最大子段和已经求出来,但是上面那种方法没有考虑到最小子段和包含头尾两个数字时的情况,所以还要再对线性的串求最大子段和,取两者中较大的那个输出。

#include <stdio.h>
long long a[100010];
int main (void)
{
	int n;
	while(scanf("%d", &n) != EOF)
	{
		int i;
		long long sum = 0, b1 = 0, b2 = 0;
		long long max1 = -0x3f3f3f3f, min = 0x3f3f3f3f;
		for(i = 0; i < n; i++)
		{
			scanf("%lld", &a[i]);
			sum += a[i];
		//求线性的串的最大子段和 
			if(b1 > 0)
				b1 += a[i];
			else
				b1 = a[i];
			if(b1 > max1)
				max1 = b1;
		//求线性的串的最小字段和 
			if(b2 < 0)
				b2 += a[i];
			else
				b2 = a[i];
			if(b2 < min)
				min = b2;		
		}
		long long max2 = sum - min;//环形的串的最大子段和 
		printf("%lld\n", max2 > max1 ? max2 : max1);//取较大的输出 
	}
	return 0;
}        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值