N个整数组成的序列a1,a2,a3,…,an,从中选出一个子段(ai,ai+1,…aj
),使这个子段的和>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 Input8 4 -1 5 -2 -1 2 6 -2Sample Output
1
我们用前缀和的思想来解决这个问题,我们定义一个结构体,在结构体内保存前缀和和位置,按照前缀和的升序排序,排序后,最小的正字段和只可能是相邻的两个差。
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int n=1e6; int a[n]; ll N; struct Node{ ll w; int p; }e[50005]; bool cmp(Node A,Node B){ return A.w<B.w; } int main(){ scanf("%lld",&N); for(int i=1;i<=N;i++){ scanf("%d",&a[i]); e[i].w=a[i]; } e[1].w=a[1]; for(int i=2;i<=N;i++){ e[i].w=e[i-1].w+a[i]; e[i].p=i; } sort(e+1,e+1+N,cmp); ll ans; if(e[1].w>0)ans=e[1].w; else ans=100000000; for(int i=2;i<=N;i++){ if(e[i].w>0&&ans>e[i].w){ ans=e[i].w; } if(e[i].w>e[i-1].w&&e[i].p>e[i-1].p&&(e[i].w-e[i-1].w)<ans){//不要忘了对位置进行判断!!! ans=e[i].w-e[i-1].w; } } printf("%lld ",ans); return 0; }
大家有疑问随时可以问的吖!!