最小正子段和

Posted -ackerman

tags:

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

 

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,是最小的。

 

输入

第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数

输出

输出最小正子段和。

输入样例

8
4
-1
5
-2
-1
2
6
-2

输出样例

1

 

 

思路:

虽然说遇到连续和会想到前缀和,但是这道题对前缀和的使用实在是太巧妙了! Orz大佬的思想:

我们记录前缀和的位置pos,以及前缀和的值val

然后对前缀和的值进行排序

然后我们找相邻的点,如果满足前面的pos小于后面的pos,它们 val 的差大于0     那么我们就记录它们的val之差

为什么是找相邻的点就可以了呢?

解释一下为什么只需检查相邻2个数就可以,设ABC是排序后的结果,如果A同B不能组成序列,而A同C可以组成序列,那么B同C也可以组成序列,并且BC会是一个更优的解。

略微证明下:

因为A和B不能组成序列,那么B的pos 小于 A的pos。 因为A和C可以组成序列,那么C的pos 大于 A的pos 

所以B和C肯定也可以组成序列!因为又是排序过了的,所以B和C的差值肯定是优于A和C的差值的

 

具体代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <string>
 5 #include <string.h>
 6 #include <set>
 7 #include <queue>
 8 #include <stdbool.h>
 9 
10 #define LL long long
11 #define inf 0x3f3f3f3f
12 using namespace std;
13 const int MAXN=50005;
14 
15 typedef struct Node
16     LL val;
17     int pos;
18 Node;
19 
20 Node a[MAXN] = 0;
21 
22 bool cmp(Node a,Node b)
23 
24     return a.val < b.val;
25 
26 
27 
28 int main()
29 
30 #ifndef ONLINE_JUDGE
31     freopen("../in.txt","r",stdin);
32 #endif
33     int n,flag;
34     LL temp;
35     LL sum = 0;
36     scanf("%d",&n);
37     a[0].val = 0;
38     a[0].pos = 0;
39     for (int i=1;i<=n;i++)
40     
41         cin >> temp;
42         sum += temp;
43         a[i].val = sum;
44         a[i].pos = i;
45     
46     sort(a,a+1+n,cmp);
47     LL res;
48     flag = 0;
49     for (int i=1;i<=n;i++)
50     
51         if (a[i].pos-a[i-1].pos>0 && a[i].val-a[i-1].val>0)
52         
53             if (flag == 0)
54             
55                 res = a[i].val-a[i-1].val;
56                 flag = 1;
57             
58             else
59             
60                 if ( a[i].val-a[i-1].val<res)
61                     res = a[i].val-a[i-1].val;
62             
63         
64     
65     cout << res << endl;
66     return 0;
67 

 

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

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

51nod 1065 最小正子段和

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

最小正子段和

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

51Nod1065 最小正子段和