zoukankan      html  css  js  c++  java
  • 最小正子段和

    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

    首先处理出前缀和数组。在前缀和数组中,我们要求的是dmin=sum[i]-sum[j](当 i>j && sum[i]-sum[j]>0 时)。
    那么就可以用一个新的结构体来存储每个sum[i]和它的编号。即 b[i].id=i; b[i].w=sum[i];
    此时sort之后我们就有了一个按照 前缀和大小 排序的带有顺序的结构体。
    之后再用一个循环去挨个遍历找相邻连个的最下差值。

    注意当 b[i].w==b[j].w 的时候,我们要让 id 大的在前面。这样的话,当有很多前缀和都相等的时候,比如 2 3 3 3 3 3 3 4,就避免了许多不必要的比较。
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    const int MAXN = 50000+3;
    using namespace std;
    typedef long long ll;
    
    int n,Min; ll a[MAXN],sum[MAXN],ans;
    
    struct B{int id;ll w;}b[MAXN];
    
    bool Com(B x,B y){
        if(x.w==y.w) return (x.id>y.id);
        return (x.w<y.w);
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            b[i].w=sum[i]=sum[i-1]+a[i];
            b[i].id=i;
        }
        
        sort(b+1,b+1+n,Com);
        if(b[1].w>0) ans=b[1].w;//注意不要忽略以a[1]开头的一段区间!!!
        else ans=0x3f3f3f3f3f3f3f3f;
        
        for(int i=2;i<=n;i++){
            int d=b[i].w-b[i-1].w;
            if(b[i].w>0 && ans>b[i].w) ans=b[i].w;//注意不要忽略以a[1]开头的一段区间!!!
            if(b[i].id>b[i-1].id && d>0 && ans>d){
                ans=(ll)b[i].w-b[i-1].w;
            }
        }
        printf("%lld",ans);
        return 0;
    }
    
    
  • 相关阅读:
    链表操作二——中间结点的删除等
    stack vector queue 等的实现方式<<0922
    任何和日期相关的函数都在这里<<0922
    类函数返回该类的问题<<0922
    Android学习笔记之PullToRefreshListView和BaseAdapter的使用
    记录Android学习过程中遇到的问题
    ruby appium 准备环境
    os x升级到10.10后appium不能测试通过的解决办法
    appium 在ios模拟器上面成功运行
    appium IOS真机测试
  • 原文地址:https://www.cnblogs.com/Siegfried-L/p/13086791.html
Copyright © 2011-2022 走看看