线性dp之最大子段和问题小结

本文深入探讨了子段和问题的各种变体,包括最大子段和、子段长度受限的子段和、环状最大子段和及两段子段和。通过线性DP、前缀和与单调队列等技巧,提供了详细的算法思路与实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

子段和问题

我们知道线性dp中一道典中典的题目就是求最大子段和;

状态方程为:dp[i]=max(dp[i]+a[i],a[i]);

当然这只是最基础的,还有很多扩展;

  1. 子段长度不大于m的最大子段和
    这个时候dp已经不好用了,可以考虑前缀和sum[i],维护min(sum[k])(i-m<=k<i),然后只要sum[i]-sum[k]就可以了,具体怎么维护可以单调队列(模板题);

  2. 子段长度不小于m的最大子段和
    (1)第一种方法,先用dp计算一次没有长度限制的最大子段和,然后
    f[i]=dp[i-1]+sum[i+m]-sum[i-1],最后对每一个f[i]求一个max;这个就是相当于在每个dp[i-1]后面加一个长度为m的段;
    (2)直接维护min(sum[k])(1<=k<=i−m),这个维护就不要单调队列,直接一遍循环维护就行;

  3. 环状最大子段和
    (1)破环为链(长度扩大两倍),然后维护一个长度不大于m(m为环的长度)的最大子段和
    (2)这种方法在后面求两段和也要用到,非常重要;
    就是考虑这个子段是否经过连接点(就是同时经过a[1]和a[n]),如果经过,可以求1-n的最小子段和,然后总和减去这个最小子段和;如果不经过,就直接求1-n的最大子段和就可以;

  4. 环状最大两段子段和
    就是第3种的一个扩展,求两段,只要正向反向维护一个最大子段和就可以;
    具体讲一下,为什么经过连接点要那样算?
    可以发现环状的最大子段和要不就是-----++++ ----++++ ----(把环拆成链,长度没有扩大两倍,加号代表该位置取,减号代表不取),要不就是++++ ------++++ ----+++,也就是说要不就经过连接点,要不就不经过;
    如果不经过,那么和普通的线性没区别;如果经过,那么就有三段子段和,不好求,正难则反,所以只要求最小子段和就可以了;
    题目:洛谷·P1121 环状最大两段子段和

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值