【51Nod - 1065】【最小正子段和】

题目:

N个整数组成的序列a11,a22,a33,…,ann,从中选出一个子序列(aii,ai+1i+1,…ajj),使这个子序列的和>0,并且这个和是所有和>0的子序列中最小的。

例如:4,-1,5,-2,-1,2,6,-2。-1,5,-2,-1,序列和为1,是最小的。

Input

第1行:整数序列的长度N(2 <= N <= 50000) 
第2 - N+1行:N个整数

Output

输出最小正子段和。

Sample Input

8
4
-1
5
-2
-1
2
6
-2

Sample Output

1

解题思路:不知道为啥,看到第一眼就行去尺取,emmm,然而我不会,在T了一次后,发现直接暴力史过不去的,所以就转化了一下思路,就是用前缀和求解,并且存储下标,然后以前缀和排序,这样就能满足相邻两位之间肯定是最小的子段和,当满足下标呈增大趋势时。

ac代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 500005
using namespace std;
typedef long long ll;
int n;
struct  node{
	ll sum;
	int pos;
}num[maxn];
//ll num[maxn];
bool cmp(const node a,const node b)
{
	return a.sum<b.sum;
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		ll summ=0;
		for(int i=1;i<=n;i++)
		{
			ll a;
			cin>>a;
			summ+=a;
			num[i].sum=summ;
			num[i].pos=i;
		}
		num[0].pos=0;
		num[0].sum=0;
		sort(num,num+n+1,cmp);
		ll ans=0;
		int flag=1;
		for(int i=1;i<=n;i++)
		{
			if(num[i].pos-num[i-1].pos>0&&num[i].sum-num[i-1].sum>0)
			{
				if(flag)
				{
					ans=num[i].sum-num[i-1].sum;
					flag=0;
				}
				else if(ans>num[i].sum-num[i-1].sum)
					ans=num[i].sum-num[i-1].sum;
			}
		}	
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42505741/article/details/81609106
今日推荐