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 }