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,是最小的。
Input
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数
Output
输出最小正子段和。
Input示例
8
4
-1
5
-2
-1
2
6
-2
Output示例
1
思路:
先求序列前缀和并标记序列号,再将前缀和进行排序。逐一比较大小相邻的两个数,当位置关系同大小关系一样,则说明区间 [ i,j ]和为正,取所有的区间中的最小值。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define endl "\n"
const int maxn = 50000+10;
struct Num{
long long val;
int pos;
}a[maxn];
bool cmp(Num A,Num B){
return A.val<B.val;
}
int main ()
{
std::ios::sync_with_stdio(false);
memset(a,0,sizeof(a));
int n;
cin>>n;
long long sum=0;
int x;
for(int i=1;i<=n;i++){
cin>>x;
sum+=x;
a[i].pos=i;
a[i].val=sum;
}
sort(a,a+n+1,cmp);
int flag=1;
sum=0;
for(int i=1;i<=n;i++){
if(a[i].val>a[i-1].val && a[i].pos>a[i-1].pos){
if(flag){
sum=a[i].val-a[i-1].val;
flag=0;
}else{
sum=min(sum,a[i].val-a[i-1].val);
}
}
}
cout<<sum<<endl;
return 0;
}