1. 程式人生 > >51nod-1065 最小正子段和 【貪心 + 思維】

51nod-1065 最小正子段和 【貪心 + 思維】

記錄 n) 51nod nta cstring pla CA 找到 class

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


解題思路:記錄前綴累加和,然後排序,檢查相鄰的兩項是否能夠組成子序列,可以的話就記錄該值D,記錄最小的D就是結果。
排序的目的是找到前綴和最接近的數。
附ac代碼:
技術分享圖片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <string>
 5 #include <cmath>
 6 #include <string>
 7 #include <iostream>
 8 #include <map>
 9 #include <queue>
10 const int maxn = 5 * 1e4 + 10;
11 const int inf = 0x3f3f3f3f
; 12 13 using namespace std; 14 typedef long long ll; 15 const ll mod = 1e9 + 7; 16 ll nu[maxn]; 17 struct nod { 18 int r; 19 ll sum; 20 }ans[maxn]; 21 bool cmp(nod a, nod b) { 22 if(a.sum < b.sum) return 1; 23 else if(a.sum == b.sum && a.r < b.r) return 1; 24 return
0; 25 } 26 int main(int argc, const char * argv[]) { 27 // int t; 28 int n; 29 scanf("%d", &n); 30 ll minn = inf; 31 for(int i = 1; i <= n; ++i) { 32 scanf("%lld", &nu[i]); 33 ans[i].sum = ans[i - 1].sum + nu[i]; 34 ans[i].r = i; 35 if(nu[i] > 0) 36 minn = min(nu[i], minn); 37 if(ans[i].sum > 0) 38 minn = min(ans[i].sum, minn); 39 } 40 // printf("%lld %lld xxxx\n", ans[2].sum, minn); 41 sort(ans + 1, ans + 1 + n, cmp); 42 43 44 for(int i = 2; i <= n; ++i) { 45 if(ans[i].r > ans[i - 1].r && ans[i].sum - ans[i - 1].sum > 0) 46 minn = min(minn, ans[i].sum - ans[i - 1].sum); 47 if(ans[i].r < ans[i - 1].r && ans[i - 1].sum - ans[i].sum > 0) 48 minn = min(minn, ans[i - 1].sum - ans[i].sum); 49 50 } 51 if(minn == inf) puts("no solution"); 52 else 53 printf("%lld\n", minn); 54 return 0; 55 }
View Code

51nod-1065 最小正子段和 【貪心 + 思維】