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

    1065 最小正子段和

    N个整数组成的序列a[1],a[2],a[3],…,a[n],从中选出一个子序列(a[i],a[i+1],…a[j]),使这个子序列的和>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
    输出最小正子段和。
    Input示例
    8
    4
    -1
    5
    -2
    -1
    2
    6
    -2
    Output示例
    1
    ———————————————————————————
    这道题维护一下前缀和 只要枚举一下区间右端点 然后求前面的比他小的最接近他的就好辣
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #define LL long long
    using namespace std;
    const int M=50007;
    const LL inf=1e15;
    int read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n;
    LL sum[M],ans=inf;
    set<LL>tr;
    int main(){
        n=read();
        tr.insert(0);
        for(int i=1;i<=n;i++){    
            sum[i]=sum[i-1]+read();
            set<LL>::iterator it=tr.lower_bound(sum[i]);
            if(it!=tr.begin()) ans=min(ans,sum[i]- *--it);
            tr.insert(sum[i]);
        }printf("%lld
    ",ans);
        return 0;
    }
    View Code

    当然也可以归并排序(其实是分治

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #define LL long long
    using namespace std;
    const int M=50007;
    const LL inf=1e15;
    int read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n;
    LL s[M],ans=inf,c[M];
    void merge(int l,int r){
        if(l==r) return ;
        int mid=(l+r)>>1;
        merge(l,mid); merge(mid+1,r);
        int cnt=l,cntl=l,cntr=mid+1;
        while(cntl<=mid&&cntr<=r){
            if(s[cntl]<s[cntr]) ans=min(ans,s[cntr]-s[cntl]),c[cnt++]=s[cntl++];
            else c[cnt++]=s[cntr++];
        }
        while(cntl<=mid) c[cnt++]=s[cntl++];
        while(cntr<=r) c[cnt++]=s[cntr++];
        for(int i=l;i<=r;i++) s[i]=c[i];
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++) s[i]=s[i-1]+read();
        merge(0,n);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
     
  • 相关阅读:
    c++中的内存管理【转载】
    c++中dynamic_cast、static_cast、reinterpret_cast和const_cast作用
    c++中的顶层const和底层const
    c++赋值操作符需要确保自我赋值的安全性问题
    二分法查找
    Servlet基础总结
    java 正则表达式:有丶东西
    HTTP协议初步认识
    Java synchronized到底锁住的是什么?
    ECMA Script 6新特性之解构赋值
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7444501.html
Copyright © 2011-2022 走看看