昨天被学军的公开赛虐傻了,才发现自己还不会用CDQ优化DP,吓得赶紧去填坑。。。
普通的CDQ就是对二分操作,计算前半部分的插入对后半部分的询问的影响。
那么如何用CDQ优化DP呢?
看一道例题:
NOI2007 cash
不难推出平方的dp方程:
f[i] = max(f[i-1], f[j]/(R[j]*A[j]+B[j])*R[j]*A[i] + f[j]/(R[j]*A[j]+B[j])*B[i]) (j<i)
复杂度是O(n^2)的
由于这些变量中并不存在单调关系,所以使不能用单调性优化的
观察式子,我们设x[j] = f[j]/(R[j]*A[j]+B[j])*R[j],y[j] = f[j]/(R[j]*A[j]+B[j])
不难吧转移方程写成如下形式
f[i] = max(f[i-1], x[j]*A[i] + y[j]*B[i]) (j<i)
点积的形式?不难发现,这样的最大值一定是在点集(x[j],y[j])的凸包上的点,更确切的说,这个点能与点(A[i],B[i])组成凸包的偏上的切线
很明显我们可以用平衡树来维护上凸壳,然后再凸壳上找到切线。
问题似乎的到了解决,但是这样的变成复杂度太高了,几乎很难在赛场上写出并调试正确。
于是我们就有了一个强有力的替代品——CDQ分治。
我们可以看到dp的过程就是不断的计算出新的f值再用其组成新的点来放进凸包中
其实我们可以把这个过程理解成这样:计算f[1],在平面上插入(x[1],y[1]),计算f[2],在平面上插入(x[2],y[2])……
这样我们就可以用CDQ分治来优化这个过程了
具体过程如下:
Solve(l,r)
Solve(l,mid)
利用f[l~