斜率优化学习笔记

发现本身傻傻分不清斜率优化和决策单调性→_→,被一些博客误导了。。因而总结一下。萌新们能够先写写[hnoi2008]玩具装箱,并不难。html


  相信有心想学习斜率优化的同志们必定本身摸索着写过[hnoi2008]玩具装箱这道题吧,我刚开始学习斜率优化的时候,也是写了这个,而后似懂非懂的发现,好像斜率优化就是先证实决策单调性,而后再用单调队列维护一下什么的,这不就是套个模板的东西吗→_→。函数

  对于某一类型的dp方程$${f[i]=Min(a[i]*b[j]+c[j]+d[i])}$$学习

  其中$a[x],b[x],c[x],d[x]$是关于$x$的函数,且$b$单增。$——————【1】$优化

  按照一向的套路,先数学概括法证实决策单调性。spa

  1.概括假设:.net

    假设有${i}$前两个决策点${j,k(j<k)}$,且${k}$的决策要比${j}$好,即:指针

$${a[i]*b[j]+c[j]+d[i]>=a[i]*b[k]+c[k]+d[i],j<k——————【2】}$$htm

  2.概括推理:blog

    此时后面有状态${i+1}$,这里咱们为了简单起见,不妨设${a[i+1]=a[i]-v,v>0}$,也就是${a}$单调递减。$${即证:a[i+1]*b[j]+c[j]+d[i+1] >= a[i+1]*b[k]+c[k]+d[i+1]}$$队列

$${(a[i]-v)*b[j]+c[j]+d[i+1] >= (a[i]-v)*b[k]+c[k]+d[i+1]}$$

$${化简得:a[i]*b[j]+v*b[k]+c[j] >= a[i]*b[k]+v*b[j]+c[k]}$$

$${~}$$

$${由【2】得:a[i]*b[j]+c[j] >= a[i]*b[k]+c[k]}$$

$${由【1】得:b[k]>b[j]}$$

$${又\because v>0}$$

$${\therefore v*b[k] >= v*b[j]}$$

$${得证}$$

  因此,决策单调性是存在的。咱们将由决策单调性得出的式子展开,化成斜率式:

$${a[i]*b[j]+c[j]+d[i]>=a[i]*b[k]+c[k]+d[i],j<k}$$

$${-a[i]>=\frac{c[k]-c[j]}{b[k]-b[j]}}$$

  记斜率$${slope(i,j)=\frac{c[k]-c[j]}{b[k]-b[j]}}$$

  而后发现这个东西很符合单调队列的尿性:

  1. ${-a[i]>=slope(q[l],q[l+1])}$。由于${q[l]}$在${q[l+1]}$以前加入,那么显然这个式子就表示${q[l]}$决策不如${q[l+1]}$优,咱们能够将队首pop掉。
  2. ${slope(q[r-1],q[r])>slope(q[r],i)}$。假设咱们在后面存在一个${a[t]}$使得${-a[t]>=slope(q[r-1],q[r])}$那么等到pop了${q[r-1]}$以后,${-a[t]}$必定也会${>=slope(q[r],i)}$,${q[r]}$也会被pop。因此说${q[r]}$其实是无用的,咱们能够直接将它pop掉。

  问题就这样优化到了${O(n)}$。

  回顾一下咱们之因此可使用斜率优化,是由于这个dp方程具备决策单调性;不然咱们推不出斜率式。以后咱们将决策单调性的式子变形为斜率式,当知足斜率式的时候就代表前一个决策不如后一个决策优,一切都是围绕着决策单调性开展的,能够说决策单调性是斜率优化的前提。(那是真的么,欲知后事,请看下文)

  如今咱们换一个角度来考虑问题,刚刚是直接从”数“的角度进行了严谨的证实,那么咱们如今从”形“的角度来意会。


  dp方程:$${f[i]=Min(a[i]*b[j]+c[j]+d[i]),b[j]单增}$$

  咱们这里沿用上面“数”的条件:${a}$单减,${b}$单增。

  移项:$${-a[i]*b[j]+f[i]=c[j]+d[i]}$$

  是否是很像直线的斜截式:${-a[i]}$为直线的斜率;直线过点:${(b[j],c[j]+d[i])}$;${f[i]}$即为直线在Y轴上的截距。

  

  能够看出,由于${f[i]}$要尽量小,因此咱们把以前小于${i}$的${j}$画在平面直角坐标系上,一如线性规划,把这条斜线自下往上平移时遇到的第一个点,即能使目前状态有最小值的点。因而咱们须要维护一个下凸壳,把那些确定不会贡献的点删掉。

  咱们用一个单调队列维护这个凸壳,由于要保证凸壳的下凸性,因此咱们显然能够获得单调队列pop队尾的条件:${slope(q[r-1],q[r])>slope(q[r],i)}$。

  考虑什么状况下pop队首元素(这里咱们的讨论都是基于${f[i]}$取最小值的状况下的):

  1. 斜率${-a[i]}$单增(由于${a}$单减)。${-a[i]>slope(q[l],q[l+1])}$。
  2. 斜率不单调。没法pop队首,二分或者三分查找队列中的最优解。二分作法:假设你要在上凸包上二分找斜率为${k}$的切线。取中间的${mid}$号点,若是${mid+1}$存在且与${mid}$点的斜率小于${k}$,则${l=mid+1}$;若是${mid-1}$存在且与${mid}$点的斜率大于${k}$,则${r=mid-1}$;若是上面两条都不知足,则${mid}$就是切点。

  不错,你必定已经发现第一种状况所对应的维护方式不是跟以前所说“数”的单调队列维护方式如出一辙吗,没错,其实这只是两种不一样的解题方式所得出来的一样的结果

  两种方法各有优缺点吧,“形”的角度比较方便理解,对于更高深的cdq分治维护凸包能够比较清晰的了解。可是遇到复杂的dp方程以及决策单调性证实就得靠“数”了(好比国王饮水记),看状况使用吧。

  以前说的决策单调性是斜率优化的基础这句话其实并不严谨,像这种从图形角度来求解的斜率优化就并无用到决策单调性。想想若是能证实决策单调性,那么必定就是对${a}$和${b}$的单调性有要求的,不然的话就是什么斜率不单调啦,在凸包上二分啦什么的。

  这就是斜率优化啦。


小科普

  回顾以前斜率优化的运用,它必需要有一个前提条件:${b}$(横坐标)单增。而若是${b[j]}$不单调怎么办呢?还能不能用斜率优化呢?

  答案是能够的,咱们须要使用CDQ分治或者splay来解决这个问题。


总结

  斜率单调暴力移指针
  斜率不单调二分找答案
  x坐标单调开单调队列
  x坐标不单调开平衡树|cdq分治


参考资料:

http://blog.sina.com.cn/s/blog_7a1746820100xztv.html

http://tieba.baidu.com/p/3671167462

http://blog.csdn.net/u010336344/article/details/52693858

相关文章
相关标签/搜索