基准时间限制:1 秒 空间限制:131072 KB 分值: 20
难度:3级算法题
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
转自光速小丸子:
对每一位来说,计算从第一位到该位置的数字的和。然后对这些和排序。
如果相近的位置上的node满足其pos的前后关系,就比较最小值,因为是相近的,所以已经是最小值候选了,其余的绝对不可能了,因为如果A到B不能形成队列,A到C形成队列了,那么B到C一定是比A到C的数值更小,而且还一定能够形成队列(A与B不能形成队列,说明posA>posB,A与C能形成队列,说明posA<posC,那就一定有posB<posC)。
这个题夹克老师太厉害了,膜拜~
另外自己还要注意一点的就是,以后一旦是连续序列这样的题目,自己第一时间需要想到的就是前缀和可能会发挥作用,碰到过好多次了还没有记性。
思路:根据权值排个序, 这样对于每个元素, 如果前后两个元素符合条件, 那么这是对于这个元素来说最优的了, 当时想 对于一个元素, 会不会有左面哪个不符合, 前面某个符合,他跟前面那个是最终答案, 手写一下pos,发现如果他跟前面那个符合, 那么他左面那个一定跟前面那个符合, 所以这永远不会是正确答案
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <cstdio>
- using namespace std;
- const int maxn = 5e4 + 7;
- typedef long long ll;
- struct node
- {
- ll val;
- int pos;
- node()
- {
- val = 0;
- pos = 0;
- }
- }a[maxn];
- int cmp(const node &a,const node &b)
- {
- if(a.val == b.val)
- return a.pos > b.pos; //贪心构造符合的数列
- return a.val < b.val;
- }
- int main()
- {
- int n;
- ll x;
- a[0].val = a[0].pos = 0;
- scanf("%d", &n);
- for(int i = 1; i <= n; i++)
- {
- scanf("%lld", &x);
- a[i].val = a[i-1].val + x;
- a[i].pos = i;
- }
- sort(a, a+1+n, cmp);