线性DP做题整合



基准时间限制: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,发现如果他跟前面那个符合, 那么他左面那个一定跟前面那个符合, 所以这永远不会是正确答案


[cpp]  view plain   copy
  1. #include <iostream>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. #include <cstdio>  
  5. using namespace std;  
  6. const int maxn = 5e4 + 7;  
  7. typedef long long ll;  
  8. struct node  
  9. {  
  10.     ll val;  
  11.     int pos;  
  12.     node()  
  13.     {  
  14.         val = 0;  
  15.         pos = 0;  
  16.     }  
  17. }a[maxn];  
  18. int cmp(const node &a,const node &b)  
  19. {  
  20.     if(a.val == b.val)  
  21.         return a.pos > b.pos;  //贪心构造符合的数列  
  22.     return a.val < b.val;  
  23. }  
  24. int main()  
  25. {  
  26.     int n;  
  27.     ll x;  
  28.     a[0].val = a[0].pos = 0;  
  29.     scanf("%d", &n);  
  30.     for(int i = 1; i <= n; i++)  
  31.     {  
  32.         scanf("%lld", &x);  
  33.         a[i].val = a[i-1].val + x;  
  34.         a[i].pos = i;  
  35.     }  
  36.     sort(a, a+1+n, cmp);  
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值