最小正子段和 贪心

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小正子段和 贪心相关的知识,希望对你有一定的参考价值。

最小正子段和
基准时间限制:1 秒 空间限制:131072 KB
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


思路:先求出前缀和,然后对前缀和进行排序,排序后求出最大的相邻前缀和之差,并且要满足:相邻前缀和在排序前的位置是递增的。输出这个答案即可

简单地考虑一下这个算法的正确性:如果没有进行排序,求前后两个前缀和的差的最大值是没有错的,暴力计算需要O(n2)的复杂度,
排序后,设此时的前缀和为sum[i],每个前缀和对应排序前的位置为p[i],相邻的前缀和如果满足更新条件,即sum[p[i]]>sum[p[i-1]]&&p[i]>p[i-1],
假设存在一个x<i-1也满足相同条件,我们令p[i]>p[x]>p[i-1]且sum[p[i]]-sum[p[x]]<sum[p[i]]-sum[p[x]],
即存在与第i个前缀和不相邻的前缀和sum[p[x]],第i个前缀和与第x个前缀和的差值要优于与第i-1的差值,那么就有sum[p[x]]>sum[p[i-1]],但是x<i-1,和排序结果是矛盾的,
所以不存在x获得排序后第i个前缀和的最优解,即最优解一定是排序后相邻前缀和的差值。

AC代码:
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int MAXN=5e4+10;
 8 const LL INF=1e15+10; 
 9 LL sum[MAXN];
10 int p[MAXN];
11 bool cmp(int a, int b){
12     return sum[a]<sum[b];
13 } 
14 int main()
15 {
16     int n,m;
17     sum[0]=0;
18     scanf("%d", &n);
19     for(int i=0;i<=n;i++) p[i]=i;
20     for(int i=1;i<=n;i++){
21         scanf("%d", &m);
22         sum[i]=sum[i-1]+m;
23     }
24     sort(p, p+n+1, cmp);
25     LL res=INF;
26     for(int i=1;i<=n;i++){
27         if(sum[p[i]]-sum[p[i-1]]>0&&p[i]>p[i-1])
28             res=min(res, sum[p[i]]-sum[p[i-1]]);
29     }
30     printf("%lld\n", res);
31 }

 

以上是关于最小正子段和 贪心的主要内容,如果未能解决你的问题,请参考以下文章

最小正子段和(前缀和+思维)

51nod 1065 最小正子段和

51Node 1065----最小正子段和

AC日记——最小正子段和 51nod 1065

最小正子段和

zznu-2060 Minsum Plus(最小正子段和)