题目:
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;
}