zoukankan      html  css  js  c++  java
  • 51nod-1065:最小正子段和(STL)

    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

    思路:对于每个前缀和,找到左边的u最大的小于sum[i]的数,两种写法:

    第一种手动维护有序数列。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=50010;
    ll a[maxn];
    vector<ll>v;
    int main()
    {
        ll N,i,j,ans=-1;
        scanf("%lld",&N);
        v.push_back(0);
        for(i=1;i<=N;i++){
            scanf("%lld",&a[i]);
            a[i]+=a[i-1];
            int pos=lower_bound(v.begin(),v.end(),a[i])-v.begin();
            if(pos-1>=0&&(ans==-1||ans>a[i]-v[pos-1])) ans=a[i]-v[pos-1];
            pos=upper_bound(v.begin(),v.end(),a[i])-v.begin();
            v.insert(v.begin()+pos,a[i]);
        }
        printf("%lld
    ",ans);
        return 0;
    }

    第二种用lower_bound+set

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll inf=1e18;
    const int maxn=50010;
    ll a[maxn];
    set<ll>s;
    int main()
    {
        ll N,i,j,ans=inf;
        scanf("%lld",&N);
        for(i=1;i<=N;i++){
            scanf("%lld",&a[i]);
            a[i]+=a[i-1];
        }
        s.insert(a[N]);
        for(i=N-1;i>=0;i--){
            ll t=*s.lower_bound(a[i]+1);
            if(t-a[i]>0) ans=min(ans,t-a[i]);
            s.insert(a[i]); 
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    经方膏方
    荆防柴朴汤
    温经汤治痤疮
    经方治疗带状疱疹
    用排除法诊断半表半里证
    leaflet 学习备忘
    在线数据库设计 初稿 想法简单验证
    SVG PATH 生成器
    模仿bootstrap做的 js tooltip (添加鼠标跟随功能)
    js 生成随机炫彩背景
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9139378.html
Copyright © 2011-2022 走看看