51Nod_1065 最小正子段和【前缀和】

                                 51Nod_1065 最小正子段和

                                     http://www.51nod.com/Challenge/Problem.html#!#problemId=1065

 

 

题目

N个整数组成的序列a[1],a[2],a[3],…,a[n],从中选出一个子序列(a[i],a[i+1],…a[j]),使这个子序列的和>0,并且这个和是所有和>0的子序列中最小的。例如:4,-1,5,-2,-1,2,6,-2。-1,5,-2,-1,序列和为1,是最小的。

输入

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

输出

输出最小正子段和。

样例输入

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

样例输出

1

分析

求出前缀和,然后对前缀和按从小到大排序,值相差最小的一定是相邻的元素,因此只要a[i].val-a[i-1].val>0,且a[i].pos>a[i-1].pos就能更新答案,要a[i].pos>a[i-1].pos是为了保证所求区间的值为正。

C++程序

#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;

const ll INF=1e18;
const int N=50005;

struct Node{
	int pos;
	ll val;
	//按val值从小到大排序 
	bool operator<(const Node &a) const
	{
		return val<a.val;
	}
}a[N];

int main()
{
	int n;
	scanf("%d",&n);
	a[0].pos=0;
	a[0].val=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i].val); 
		a[i].val+=a[i-1].val;
		a[i].pos=i;
	}
	sort(a,a+n+1);
	ll res=INF;
	for(int i=1;i<=n;i++)
	{
		ll tmp=a[i].val-a[i-1].val;
		if(a[i].pos>a[i-1].pos&&tmp>0)//跳过tmp=0的情况 
		  res=min(res,tmp);
	}
	cout<<res<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值