动态规划-最大子段和其变式

最大子段和

给出一个长度为 \(n\) 的序列 \(a\),选出其中连续且非空的一段使得这段和最大。

\(O(n^3)\) :枚举左右端点,再进行 \(O(n)\) 求和。

\(O(n^2)\) :同上,求和使用前缀和优化 \(O(1)\) 查询。

\(O(n)\) : DP写法//
模拟求最大子段和的过程,从左到右顺序遍历,从第一个数开始考虑,考虑到第1个数时,此时以1为结尾最大子段和为a[1]。考虑第二个数如果a[1]+a[2]>a[2],此时以2为结尾的最大子段和是a[1]+a[2],如果a[1]+a[2]<a[2],此时以2为结尾的最大子段和是a[2]。

状态:所以我们可以顺序遍历,考虑以i为结尾的子段,是自己自创门派还是和邻居一起会获得更优的结果。因此我们可以设计状态为 f[i]为结尾,获得的最大连续子段和。
转移:

  1. a[i]+f[i-1]>a[i] 和邻居合伙的收益更大。$ f[i]=a[i]+f[i-1]$
  2. a[i]+f[i-1]<a[i] 自创门派的收益更大 $ f[i]=a[i]$
  3. a[i]+f[i-1]=a[i] 收益好像一样,那该怎么?其实加不加上没影响。如果加上的话就可以。连接两段,使你的最大子段和更长。

长度等于、大于、小于k的最大子段和

暴力算法同上

等于:\(O(n)\) 单调队列,顺序遍历,求出 i-m+1 到 i 子段和,维护最大子段和。

大于:\(O(n*m)\) 单调队列,顺序遍历,枚举\(k(k<i-m+1)\)求出 k 到 i子段和,维护最大子段和。

小于:\(O(n*m)\) 单调队列,顺序遍历,枚举\(k(i-m+1<k<=i)\)求出 i 到 k子段和,维护最大子段和。

环状最大子段和

处理环型的问题都有一个通用的解法 将数据复制一份在末尾,环的问题就变成的普通的链的问题。

最大两端子段和

\(O(n)\) 考虑枚举两端和中间的空点,只需要求出 空点左侧的子段最大和和空点右侧的子段最大和,再维护两端最大和即可。空点左右侧的最大和,可以通过预处理的得到。


参考文献

  1. 题解 P1115 【最大子段和】by_Arahc_
  2. P1121 环状最大两段子段和 题解 byDevelop
posted @ 2024-02-02 16:16  Wh1sky  阅读(50)  评论(0)    收藏  举报