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

有一个很好的思路,出自https://bbs.csdn.net/topics/370106383
先计算前缀和,比如样例为 4 3 8 6 5 7 13 11,只要求相邻两个数差最小的那个就是了。si < sj并且i < j,当然直接找的会是O(n2),所以可以先排序,值取相邻两个数。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 1e5+10;
 5 struct Nod{
 6     ll id1, id2, num;
 7 }nod[N];
 8 bool cmp(Nod &a, Nod &b) {
 9     return a.num < b.num;
10 }
11 int main() {
12     int n;
13     cin >> n;
14     nod[0].num = nod[0].id1 = nod[0].id2 = 0;
15     for(int i = 1; i <= n; i ++) {
16         cin >> nod[i].num;
17         nod[i].num += nod[i-1].num;
18         nod[i].id1 = nod[i].id2 = i;
19     }
20     sort(nod,nod+1+n,cmp);
21     int cnt = 0;
22     for(int i = 1; i <= n; i ++) {
23         if(nod[i].num == nod[cnt].num) {
24             nod[cnt].id1 = min(nod[i].id1,nod[cnt].id1);
25             nod[cnt].id2 = max(nod[i].id2,nod[cnt].id2);
26         } else nod[++cnt] = nod[i];
27     }
28     ll MIN = 1e7;
29     for(int i = 0; i < cnt; i ++) {
30         if(nod[i].id1<nod[i+1].id2 && nod[i+1].num-nod[i].num > 0 && (nod[i+1].num-nod[i].num) < MIN) {
31             MIN = nod[i+1].num - nod[i].num;
32         }
33     }
34     cout << MIN << endl;
35     return 0;
36 }

 

posted @ 2018-04-24 18:39  starry_sky  阅读(172)  评论(0编辑  收藏  举报