pku3709 dp单调队列优化

我是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删去了。

  恩,大概思想就是这样的。

附程序:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值