斜率优化Convex Hull Trick

斜率优化

一、简单DP

首先从一道简单题引入。

[IOI2002]任务安排

Description

N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和(同一批任务将在同一时刻完成)。每个任务的费用是它的完成时刻乘以一个费用系数ci。请确定一个分组方案,使得总费用最小。

例如:S=1;T={1,3,4,2,1};F={3,2,3,3,4}。如果分组方案是{1,2}、{3}、{4,5},则完成时间分别为{5,5,10,14,14},费用C={15,10,30,42,56},总费用就是153。

Input

第一行是N(1<=N<=5000)。

第二行是S(0<=S<=50)。

下面N行每行有一对数,分别为Ti和ci,均为不大于100的正整数,表示第i个任务单独完成所需的时间是Ti及其费用系数ci。

Output

一个数,最小的总费用。

Sample Input

5

1

1 3

3 2

4 3

2 3

1 4

Sample Output

153

Solution

“光着身子”的动态规划。

设F[i,j]表示划分前i个任务为j批的最小费用。

F[i,j]=min(F[k,j-1]+(s*j+\sum_{q=k+1}^{i}t[q] ))*(\sum_{q=k+1}^{i}c[q]))

设T[i]=\sum_{j=1}^{i}t[j]                 C[i]=\sum_{j=1}^{i}c[i]

F[i,j]=min(F[k,j-1]+(s*j+T[i]-T[k] ))*(C[i]-C[k]))

(2D/1D),时间复杂度:O(n^3),空间复杂度:O(n^2)

这显然是不够的。

 

实际上我们不一定要知道之前划分了多少批任务,只需要记录F[i]表示划分前i个任务的最小费用。

F[i]=min(F[j]+(s+T[i])*(C[i]-C[j]))+s*(C[n]-C[i])

这样就写出了(1D/1D)动态规划方程。

二、简单题2

将上题的n<=5000改为n<=300000。

Solution

这就是本文的重点所在了。

在上文中的(1D/1D)动态规划中,尚有两种简单的优化思路:

  1. 优化状态:将这样一个动态规划转化为贪心或数学题。
  2. 优化转移:优化转移的时间(主要为优化重复或不必要的转移)。

显然,优化状态很难达成,那么我们考虑优化转移。

我们可以发现在转移的过程中有很多的不必要的转移:

考虑一下两个转移:

F[i]=min(F[j]+(s+T[i])*(C[i]-C[j]))+s*(C[n]-C[i])

F[i]=min(F[k]+(s+T[i])*(C[i]-C[k]))+s*(C[n]-C[i])

(j<k<i)

在此题中,若 min(F[j]+(s+T[i])*(C[i]-C[j]))\geqslant min(F[k]+(s+T[i])*(C[i]-C[k]))

那么转移 j 就是不必要的。

也就是说,若有(i'>i)且选取转移状态的集合\begin{Bmatrix} i':& j1, &j2, &... &j\alpha \end{Bmatrix}\subseteq \begin{Bmatrix} i:& j1, &j2, &... &j\beta \end{Bmatrix}

并且存在,后面的转移比前面的优,则前面的转移就是无意义的,也就是对最终答案无贡献的了。

 

考虑本题,如何判断转移状态是否是有用的呢?

F[j]+(s+T[i])*(C[i]-C[j])\geqslant F[k]+(s+T[i])*(C[i]-C[k])

\therefore F[j]-s*c[j]-T[i]*c[j]\geqslant F[k]-s*c[k]-T[i]*c[k]

\therefore F[j]-f[k]+s*(c[k]-c[j])\geqslant T[i]*(c[j]-c[k])

\therefore \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]

也就是说,如果 \small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]

那么后面的转移比前面的优,否则前面的转移比后面的优。

这样的\small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) },即是用斜率的形式,表现了转移之间的不必要的关系。

 

进一步,我们发现:

\small \frac{F[j]-f[k]+s*(c[k]-c[j]))}{(c[j]-c[k]) }\leqslant T[i]\leqslant T[i+1]

也就是说,如果当前存在后面的转移比前面的优,那么这个转移在之后的状态中都不会成为最有转移!

根据这个性质,我们选择用单调队列维护一个两点间斜率单调递增的点集队列。

设:

\small g(x1,x2)=\frac{F[x1]-f[x2]+s*(c[x2]-c[x1]))}{(c[x1]-c[x2]) }

  1. 若有  \small g(x1,x2)\geqslant g(x2,x3),则\small x2的转移必然不会是最优的,于是能够将它删除。(维护队尾)
  2. 若有\small g(x1,x2)<=T[i],        则x1的转移必然不会是最优的,于是能够将它删除。 (维护队首)

最后的点集队列满足:在队首的点的转移必然是最优的。

于是\small F[i]=F[que[head]]+(s+T[i])*(C[i]-C[que[head]])+s*(C[n]-C[i])

将转移化为O(1)(1D/0D)动态规划完成。

三、简单题3

若   -512<=t[i]<=512 ,也就是说:

\small T[i]\leqslant T[i+1]    不再成立怎么办呢?

我们发现:

  1. 若有  \small g(x1,x2)\geqslant g(x2,x3),则\small x2的转移必然不会是最优的,于是能够将它删除。(维护队尾)

这一性质依然成立,那么这个点集集合还是会组成一个相邻点斜率递增的单调队列。

\small g(x1,x2)\leqslant g(x2,x3)...\leqslant g(x\alpha ,x\alpha+1 )<=T[i]<=g()...   

发现:

  1. 如果\small g(x\alpha ,x\alpha+1 )< T[i],那么\small x\alpha +1优于\small x\alpha
  2. 如果\small g(x\alpha ,x\alpha+1 )> T[i],那么\small x\alpha优于\small x\alpha +1

也就是说,答案一定存在于一个点\small x\alpha,使得g(x\alpha-1,x\alpha ) \leqslant T[i] 且 g(x\alpha,x\alpha +1) \geqslant T[i]

那么\small x\alpha必然最优。

我们可以维护单调队列,只在队尾删除,每次二分查询一个最优点。

这样便是O(nlgn)的斜率优化做法。

 

四、简单题4

一种形式斜率优化的形式:

队列中的点不满足单调性。

BZOJ1492: [NOI2007]货币兑换Cash

题目描述:详见BZOJ。

这一题就是典型的例子。

斜率不单调,那么就必须用cdq分治或splay维护斜率凸包解决斜率优化问题了。

下次有时间再补充。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值