我是dp菜的,尤其是对这种斜率优化的题目,从来都没写对过。膜拜apio金牌kib当场写对了那到题,我才20分朴素…………
jinpaikib=jib。。。
低调,这句话是教主说的,膜拜教主两铜。
好吧,其实dp的优化写起来很简单,但是推导过程也很简单,主要是看你掌握的怎么样,我就属于掌握的不怎么样。
题目大意:
给你一列数,这列数单调非减,然后让你把这列数分成若干部分,每个部分数的个数不小于m,求每个的每个数减去每个部分最小数的差的和的最小值。。。
简略题解:
其实不难发现,f[i]=max{f[j]+sum[i]-sum[j]-a[j+1]*(i-j)}
但是这个显然是平方级算法,如何优化呢?
额,一个很明显的斜率优化。
我们看,当k<j的时候,对于i,如果k比j更优,那么满足
f[k]+sum[i]-sum[k]-a[k+1]*(i-k)<f[j]+sum[i]-sum[j]-a[j+1]*(i-j)
好的,我们整理一下,得到了
f[k]-f[j]+sum[j]-sum[k]-j*a[j+1]+k*a[k+1]<i*(a[k+1]-a[j+1])
设g(k,j)=f[k]-f[j]+sum[j]-sum[k]-j*a[j+1]+k*a[k+1]
s(k,j)=s[k+1]-s[j+1]
这个代表什么呢,左边完全是关于k和j的,右边只有一个i,那么把右边的a[k+1]-a[j+1]除到左边来,我们就得到了一个左边完全关于k和j的东西,右边是i。好,我们设p=(f[k]-f[j]+sum[j]-sum[k]-j*a[j+1]+k*a[k+1])/(a[k+1]-a[j+1]),容易发现p的值是固定的,所以k和j哪一个更优取决于p夹在哪两个i之间。
那么好,对于三个东西i<j<k,如果g(k,j)/s(k,j)<g(j,i)/s(j,i),那么也就表示要么i比j优要么k比j优,这个很像凸包。这样的话就可以把j删去了。
恩,大概思想就是这样的。
附程序: