zoukankan      html  css  js  c++  java
  • 「学习笔记」斜率优化

    太久没碰过这个玩意了,于是它就变成学习笔记了。

    题目特点

    一般来说,斜率优化的dp会比其它的dp得到转移方程要简单一点点。

    通式大概是:

    [f[i] = a(i)b(j) + c(i) + d(j) ]

    也就是说,这种dp和单调队列不同的一点是有同时和(i,j)有关的项,这时候就需要用到斜率优化。

    拿道题目来讲可能效果更好一些。

    P3195 [HNOI2008]玩具装箱

    设前缀和为(s(i)),那么很快得到dp方程:

    [f[i] = min_{j < i}{f[j] + (s(i) + i - s(j) - j - L - 1)^2 } ]

    (a(i) = s(i) + i, b(i) = a(i) + L + 1)

    于是

    [egin{aligned}f[i] &= f[j] + (a(i) - b(j))^2 \&= f[j] + a(i)^2 - 2a(i)b(j) + b(j)^2end{aligned} ]

    移项可得

    [2 a(i)b(j) + f[i] - a(i)^2 = f[j] + b(j)^2 ]

    (b(j) = x, f[j]+b(j)^2 = y),那么这个方程就可以看成一条平面直角坐标系上的一条直线。

    此时(f[i])的含义变为,当这条直线经过点(P(x, y))时,与(y)轴的截距加(a(i)^2)的值((a(i)^2)是一个定值)。

    于是我们只需要找到这个斜率的最小值。

    我们可以画一个图辅助理解。(图源oi-wiki,侵删)

    那么我们可以用一个单调队列维护下凸包就可以了。

    由于在这道题中,斜率是单调递增的,所以我们可以将队头斜率小于当前斜率的点全部弹掉,取队头为转移点即可。

    P5504 [JSOI2011]柠檬

    首先需要知道一个性质:每一段左右两端的贝壳大小相同,而且这一段的(s_0)即为左右两端贝壳的大小。

    那么考虑dp,设(f[i])表示前(i)个数能够获得的最多柠檬数,(c_i)表示这种大小第几次出现。

    那么有

    [f[i] = max_{j leq i, s_i = s_j}{f[j - 1] + s_i(c_i - c_j + 1)^2 } ]

    把所有项拆开有:

    [f[i] = f[j - 1] + s_ic_i^2 - 2s_ic_ic_j+s_ic_j^2+2s_ic_i-2s_ic_j+s_i ]

    移项可得:

    [f[j - 1] - 2s_ic_j + s_ic_j^2 = f[i] - 2s_ic_i - s_ic_i^2 + s_i + 2s_ic_ic_j ]

    (c_j = x, f[j - 1] - 2s_ic_j + s_ic_j^2 = y),就可以像上一道题那样写出一条直线来。

    于是我们对每种颜色用单调栈维护上凸包,由于斜率单调递增,所以我们可以将队尾斜率小于当前斜率的点全部弹掉,同时取队尾为转移点即可。

  • 相关阅读:
    nohup
    MYSQL提权总结
    udf提权方法和出现问题汇总
    windows 2012 抓明文密码方法
    用CPAU替代RUNAS
    MS15-034 HTTP.sys (IIS) DoS And Possible Remote Code Execution – AGGIORNAMENTO CRITICO
    php注入专题
    Mysql 另类盲注中的一些技巧
    Elasticsearch Groovy任意命令执行漏洞EXP
    linux好用的擦屁股工具
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/11727539.html
Copyright © 2011-2022 走看看