• 浅谈斜率优化


    斜率优化

    如果对于方程形如这样的

    我们不能对其进行比较有效果的优化,因为它的转移,涉及到了关于i和关于j的一些数组,这时我们就需要用斜率优化了。

    通常我们令k<j<i,且用j来更新F[i]比用j优。则有

    并且我们都可以化成如下形式,X[j],Y[j]指只关于j的数,X[k],Y[k]亦之

    我们可以根据这个式子,来优化DP。这大概就是斜率优化的主要思想

    实践出真知,让我们看一下HDU3507

    很容易可以推出状态转移方程

    令k<j<i,那么就可以得到

     

    移项可得

    如果我们令Y[i]=F[i]+A[i]²,X[i]=A[i],那么可以转化成如上形式

    优化DP

    根据刚才的推算,可以发现,要是满足这个条件的转移,选j一定比k要优。

    我们抽象的把X[i],Y[i]想象成平面上的点,那么这个式子所表示的含义就是两个点所连成的这条线的斜率。

    但是这个斜率又是怎么样的呢?

    我们令g(i,j)表示i点和j点的斜率(上面式子的左边,k<j<i)。假设g(i,j)<g(j,k)。①如果g(i,j)<F[i](这个F[i]斜率式子右边的F[i])那么i一定比j优,则j不必选。②如果g(i,j)>F[i],那么j比i优,但是k又比j优,还是不选j。

    总结出来,如果g(i,j)<g(j,k),那么j就是废物,可以T掉。

    我们发现,这种情况就是

    那么最后剩下的图形,就是一个下凸包壳,也就是斜率单调

    优化实现

    我们就例题而言

    维护一个单调队列p.get为斜率

    表示存的可能为答案的点。因为我们要维护下凸包的性质,必须满足get(p[tail-1],p[tail])>get(p[tail],i)

    我们根据斜率式子,队首必须满足get(p[head],p[head+1])<2A[i]

    因为斜率越小越优,所以每次选队首。

    大致可以有如下代码:

    while (head<tail) and (get(p[tail-1],p[tail])>get(p[tail],i)) do dec(tail);

    加入新增可供转移的节点

    while (head<tail) and (get(p[head],p[head+1])<...) do inc(HeaD)

    动态规划转移

    练习题

    bzoj1010[HNOI2008]玩具装箱 

    bzoj1096[ZJOI2007]仓库建设

    bzoj1597[USACP2008 Mar]土地购买 

    bzoj1911[Apio2010]特别行动队 

    bzoj3156 防御准备 

    bzoj3675[Apio2014] 序列分割 

    bzoj3437 小P的牧场 

    bzoj4518[SDOI2016] 征途 

  • 相关阅读:
    postgreSQL中的case用法说明
    UOJ#749[UNR #6]稳健型选手【贪心,分治,主席树】
    CF1286EFedya the Potter Strikes Back【KMP,RMQ】
    AT2366[AGC012F]Prefix Median【dp】
    P8352[SDOI/SXOI2022]小N的独立集【dp套dp】
    uoj#750[UNR #6]小火车【二分,折半,鸽笼原理】
    AT2382[AGC015D]A or...or B Problem
    UOJ#748[UNR #6]机器人表演【dp】
    CF1427FBoring Card Game【贪心】
    CF1534F2Falling Sand (Hard Version)
  • 原文地址:https://www.cnblogs.com/philchieh/p/8044577.html
Copyright © 2020-2023  润新知