51NOD 1065 最小正子段和

来源:互联网 发布:thinkphp投票系统源码 编辑:程序博客网 时间:2024/05/17 21:51

1065 最小正子段和
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题

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


问题其实就是找出 min(sum[j]-sum[i]) {1 < i < j < n+1}
然后很自然的想到2分 平衡树 于是STL水过
set中sum[j]的迭代器-1要找的sum[i]

#include<iostream>#include<stdlib.h>#include<stdio.h>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<time.h>#include<math.h>#include<list>#include<cstring>#include<fstream>//#include<memory.h>using namespace std;#define ll long long#define ull unsigned long long#define pii pair<int,int>#define INF 1000000007#define pll pair<ll,ll>#define pid pair<int,double>//#define CHECK_TIMEll sum[50001];set<ll>exist;int main(){    //freopen("/home/lu/文档/r.txt","r",stdin);    //freopen("/home/lu/文档/w.txt","w",stdout);    int n;    scanf("%d",&n);    for(int i=1;i<=n;++i)        scanf("%lld",sum+i);    ll res=INF;    exist.insert(0);    for(int i=1;i<=n;++i){        sum[i]+=sum[i-1];        exist.insert(sum[i]);        set<ll>::iterator it=exist.find(sum[i]);        if(it!=exist.cbegin()){            ll t=sum[i]-*(--it);            if(t>0)                res=min(t,res);        }    }    printf("%lld\n",res);    return 0;}
0 0
原创粉丝点击