51nod-1065 最小正子段和 贪心 + 思维
Posted euzmin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod-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
解题思路:记录前缀累加和,然后排序,检查相邻的两项是否能够组成子序列,可以的话就记录该值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 }
以上是关于51nod-1065 最小正子段和 贪心 + 思维的主要内容,如果未能解决你的问题,请参考以下文章