最小正字段和

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 Input
8
4
-1
5
-2
-1
2
6
-2
Sample 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;
}

大家有疑问随时可以问的吖!!

原文地址:https://www.cnblogs.com/LightyaChoo/p/13086345.html