基准时间限制:1 秒 空间限制:131072 KB 分值: 20
难度:3级算法题
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,是最小的。
Input
第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数
Output
输出最小正子段和。
Input示例
8 4 -1 5 -2 -1 2 6 -2
Output示例
1
思路:计算前i项和,赋值a[i].num,赋值a[i].id为i。注意i从1开始。
i=0时,a[0].num=0,a[0].id=0,表示从头到i的
从小到大排序后,比较a[i].num-a[i-1].num与minn大小。只比较两个连续的即可。
为什么只比较两个连续的??
比如:ABC是排序后的,AB不能组成序列,BC能,那AC一定能,且BC最优。
因为ABC是由小到大排序,BC一定比AC小。
代码:
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int id;
long long num;
}a[50005];
int n;
int cmp(node a,node b)
{
return a.num<b.num;
}
int main()
{
cin>>n;
int s;
long long sum=0,minn;
a[0].id=0;
a[0].num=0;
for(int i=1;i<=n;i++)
{
cin>>s;
sum+=s;
a[i].id=i;
a[i].num=sum;
}
sort(a,a+n+1,cmp); //注意+1
int flag=0;
for(int i=1;i<=n;i++)
{
if(a[i].id>a[i-1].id&&a[i].num>a[i-1].num)
{
long long h=a[i].num-a[i-1].num;
if(flag==0)
{
flag=1;
minn=h;
//cout<<minn<<endl;
}
else
{
//cout<<minn<<endl;
if(h<minn)
//cout<<a[i].num-a[i-1].num<<" ";
minn=h;
//cout<<minn<<endl;
}
}
}
cout<<minn<<endl;
return 0;
}