• 斜率优化


    斜率优化


    1.概念

    对于某些转移方程形如(DP[i] = min / max(DP[j] + f(j)))的DP来说,我们可以使用单调队列将其由(O(n^{2}))优化为(O(n))。但对于一些转移方程形如(DP[i] = min / max(DP[j] + f(i , j)))的DP来说,因为转移中有与(i)有关的表达式,于是就不能贸然地使用单调队列了。这个时候我们需要将斜率优化请上台面。

    我们以转移方程形如(DP[i] = min(DP[j] + f(i, j)))的DP为例。

    尝试将DP方程化为(DP[i] = {color{red}{(……)}} + {color{green}{(……)}} +{color{orange}{(……)}})的形式。红色的部分为仅与(j)有关的表达式,绿色的部分则与(i)(j)均有关,橙色的部分只与(i)或常数有关。设红色部分为(y),绿色的部分中与(i)有关的部分为(k),与(j)有关的部分为(x),橙色的部分向左移项与(DP[i])合为(B),这样我们就将其化成了(B = y - kx)的形式,整个问题就转化成了求(B)最小。因为在(B)中与(i)有关的部分在单次转移时相当于一个常数,所以求(B)最小就相当于求(DP[i])最小。

    对于任意(j),可以表示为坐标轴上一点((x, y)),转移时则可利用坐标计算(y - kx),求得(B)的最小值(当然算的时候别忘了计算(B)中的常数)。保证斜率(k >0),且随(i)单增,才可以进行下面的转移。

    如何确定转移最优一点呢?这样:

    example 1

    将斜率为(k)的直线上移,可发现第一个触及直线的点会使其截距最小。而又因为斜率单增,所以说此点前的所有点已经对转移没有贡献,直接弹出即可。

    如果尾部在插入新的(j)时出现了不下凸的情况怎么办?这样:

    example 2

    (i)点之上的两个点在(i)点插入后,将不会有对转移做出贡献的机会,因为由(i)点转移至当前点时所得到的截距将恒优于(i)点之上的两个点。所以此两点一并弹出即可。

    或使用数学方法证明:记(slope(i, j) = dfrac{Y(i) - Y(j)}{X(i) - X(j)}),当前点为(l)。若(slope(i, j) < k (i < j)),则说明由(j)转移到(l)较由(i)转移到(l)更优。假设(slope(i, j) > slope(j, l)),若(slope(j, l) < k),则(l)(j)更优;若(slope(j, l)>k),则(slope(i, j)>k),说明(i)(j)更优。

    这样的话不论怎样,出现上凸的(j)点都不会是更优的转移点,所以说直接将(j)点删除,再(i,l)相连即可。

    存点的结构考虑单调队列,因其可以按条件进行双向删除,单向插入,符合需求。

    维护队首时,比较(slope(head, head + 1))是否小于(k)。小于(k)说明此点在所求点之下,弹出。第一个(slope(…) geqslant k)的点即为所求转移点。(PS:如果弹到队尾都没有符合要求的点,则至少要留下一个点转移。)

    维护队尾时考虑上述证明,弹出(slope(tail, i) < slope(tail - 1, tail))(tail)。这个就不用留点了,因为到最后还会插入一个(i)

    成型后的有效点集大概这样,是个上凸包。

    example 3

    大概就这样。

    那么如果(k)(i)单减,转移方程求的是最小值呢?维护一个上凸包即可(维护单调队列时把小于号都反过来)。

    上面所说的均是(x)单调且(k)单调的情况,那如果它们不单调呢?据说(x)不单调可以开平衡树或cdq分治,(k)不单调二分查找。然而我并不会:P

    没了。

    2.例题

    直接看博客即可。

    1.[HNOI 2008]玩具装箱

    传送门

    2.[USACO08MAR] 土地购买 Land Acquisition

    传送门

    有不正确之处请不吝赐教。评论区在下方,若评论框过小右下角拖动即可。谢谢。

  • 相关阅读:
    设计教训。
    爆牙齿的世界杯日记(小组末轮AB组)
    [维多利亚2 MOD] RecoverMingV(Vic2版复明) V1.1.3(201254更新),兼容AHD 2.31beta
    [文明5建筑MOD] Gunpowder Magazine and Firecracker Workshop (火药库与爆竹坊)。祝大家春节快乐!
    IVY Bridge : There's more than 22nm(IVB的新指令)
    ID3D11DeviceContext::Dispatch与numthread笔记
    如何在各个版本的VC及64位下使用CPUID指令
    [x86]SIMD指令集发展历程表(MMX、SSE、AVX等)
    C++AMP的tiled_index线程编号属性笔记
    x264编码参数大测试:09 trellis(crf26)
  • 原文地址:https://www.cnblogs.com/manziqi/p/9160365.html
Copyright © 2020-2023  润新知