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
思路:
先求一遍前缀和,然后对于一个数想办法找他后面的数中大于他的最小值,他俩的差值就是结果。这里用到set,倒着扫,对一个数先用upper_bound找set中大于他的最小的元素,因为倒着扫的,所以这些元素都保证在他后面,找到他俩的差值与最优解做比较赋值给最优解。注意数组从1开始读,要倒着枚举要枚举0元素。因为枚举0号代表数组从头选,否则就会少了这一点。
ac代码:
#include<bits/stdc++.h>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=50010;
ll a[maxn];
set<ll> ss;
set<ll> ::iterator it;
int main(){int n;cin>>n; for(int i=1;i<=n;i++){scanf("%lld",&a[i]);a[i]+=a[i-1];}ll ans=0x3f3f3f3f;for(int i=n;i>=0;i--){it=ss.upper_bound(a[i]);ss.insert(a[i]);if(it!=ss.end()){ans=min(ans,*it-a[i]);}}printf("%lld\n",ans);return 0;
}