[HDU3507] [2010多校联考7] Print Article [斜率优化][dp]

[ L i n k \frak{Link} Link]


∑ a = 1 n ∑ b = 1 n ∑ c = 1 n ∑ d = 1 n ∑ e = 1 n ∑ f = 1 n ∑ g = 1 n ∑ h = 1 n ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n ∑ l = 1 n ∑ m = 1 n ∑ n = 1 n ∑ o = 1 n ∑ p = 1 n ∑ q = 1 n ∑ r = 1 n ∑ s = 1 n ∑ t = 1 n ∑ u = 1 n ∑ v = 1 n ∑ w = 1 n ∑ x = 1 n ∑ y = 1 n ∑ z = 1 n \mathcal{\sum\limits_{a=1}^n\sum\limits_{b=1}^n\sum\limits_{c=1}^n\sum\limits_{d=1}^n\sum\limits_{e=1}^n\sum\limits_{f=1}^n\sum\limits_{g=1}^n\sum\limits_{h=1}^n\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sum\limits_{k=1}^n\sum\limits_{l=1}^n\sum\limits_{m=1}^n\sum\limits_{n=1}^n\sum\limits_{o=1}^n\sum\limits_{p=1}^n\sum\limits_{q=1}^n\sum\limits_{r=1}^n\sum\limits_{s=1}^n\sum\limits_{t=1}^n\sum\limits_{u=1}^n\sum\limits_{v=1}^n\sum\limits_{w=1}^n\sum\limits_{x=1}^n\sum\limits_{y=1}^n\sum\limits_{z=1}^n} a=1nb=1nc=1nd=1ne=1nf=1ng=1nh=1ni=1nj=1nk=1nl=1nm=1nn=1no=1np=1nq=1nr=1ns=1nt=1nu=1nv=1nw=1nx=1ny=1nz=1n


注意有多组数据。
题目摆了一个大大的 ( ∑ i = 1 k C i ) 2 + M \mathcal{(\sum\limits_{i=1}^k C_i)^2+M} (i=1kCi)2+M
前缀和、区间和记为 S ( i ) \mathcal{S(i)} S(i) S ( i , j ) \mathcal{S(i,j)} S(i,j)
非常显然的 d p \mathcal{dp} dp,先裂一个柿子 F ( i ) = m i n { F ( j ) + c o s t ( j + 1... i ) } \mathcal{F(i)=min\{F(j)+cost(j+1...i)\}} F(i)=min{F(j)+cost(j+1...i)}也即
F ( i ) = m i n { F ( j ) + M + [ S ( i ) − S ( j − 1 ) ] 2 } , j ∈ [ 1 , i ) \mathcal{F(i)=min\{F(j)+M+[S(i)-S(j-1)]^2\},j\in[1,i)} F(i)=min{F(j)+M+[S(i)S(j1)]2},j[1,i)这布星 Θ ( n 2 ) \mathcal{\Theta(n^2)} Θ(n2)
上面的柿子比较好康,容易联想到单调队列 F ( i ) = m a x / m i n { F ( j ) + G ( j ) } \mathcal{F(i)=max/min\{F(j)+G(j)\}} F(i)=max/min{F(j)+G(j)}
然鹅形式是 F ( i ) = m a x / m i n { F ( j ) + G ( i , j ) } \mathcal{F(i)=max/min\{F(j)+G(i,j)\}} F(i)=max/min{F(j)+G(i,j)};怎么拌?


这一部分讨论的不是常规的单调队列+斜率优化,可以先看下面的再上来
没办法化成别的什么形式。有没有决策单调性?
我们现在 i − 1 \mathcal{i-1} i1 j \mathcal{j} j转移过来, i \mathcal{i} i j ′ \mathcal{j'} j转移过来,有没有 j ′ ≥ j \mathcal{j'\ge j} jj
比如 ( ∑ i = 1 k C i ) 2 + M \mathcal{(\sum\limits_{i=1}^k C_i)^2+M} (i=1kCi)2+M现在 + + i \mathcal{++i} ++i变成 ( ∑ i = 1 k C i ) 2 + 2 ( ∑ i = 1 k C i ) C i + 1 + C i + 1 2 + M \mathcal{(\sum\limits_{i=1}^kC_i)^2+2(\sum\limits_{i=1}^kC_i)C_{i+1}+C_{i+1}^2+M} (i=1kCi)2+2(i=1kCi)Ci+1+Ci+12+M
如果多分一份就是 ( ∑ i = 1 k C i ) 2 + C i + 1 2 + 2 M \mathcal{(\sum\limits_{i=1}^k C_i)^2+C_{i+1}^2+2M} (i=1kCi)2+Ci+12+2M Δ = M − 2 ( ∑ i = 1 k C i ) C i + 1 \mathcal{\Delta=M-2(\sum\limits_{i=1}^kC_i)C_{i+1}} Δ=M2(i=1kCi)Ci+1
多分一份优即 Δ ≤ 0 \mathcal{\Delta\le0} Δ0那么已经多分一份了之后决策就不会把多分这一份的时间推前。
因为推前了,前面亏、后面也亏。推后倒是有可能的。
于是我们 f a \mathcal{fa} fa现了这样一个十分简单好写的决策单调性——这题连决策点都是单调的
然后就可以愉快 Θ ( n ) \mathcal{\Theta(n)} Θ(n)
我不会证所以这些都是扯淡,大家可以自己试一试
决策单调性是不是看起来有点像贪心啊

了解斜率优化过后这种做法可能更好理解。
如果把斜率优化那个过程模拟一下,又因为这道题 F u n c i o n O f ( k ) \mathcal{FuncionOf(k)} FuncionOf(k)有个单调性,
不难发现决策点一定是越来越靠后的。所以……
事实上(至少对于这道题目)好像没有必要开个单调队列吧?
嗯嗯?唔呣???


#include<cstdio>
long long s[500005], f[500005];
int n, m;
int main() {
	while (~scanf("%d%d", &n, &m)) {
		for (int i(1); i <= n; s[i] += s[i-1], ++i) scanf("%lld", &s[i]);
		for (int i(1), p(0); i <= n; ++i) {
			f[i] = s[i] * s[i] + m;
			for (int j(p); j < i; ++j) {
				long long temp(f[j] + (s[i] - s[j]) * (s[i] - s[j]) + m);
				if (temp <= f[i]) f[i] = temp, p = j;
			}
		} printf("%lld\n", f[n]);
	} return 0;
}

斜率优化
式子形如 F ( i ) = m i n { F ( j ) + G ( i , j ) } \mathcal{F(i)=min\{F(j)+G(i,j)\}} F(i)=min{F(j)+G(i,j)}
现在我们要找到用前面的哪个决策来更新当前决策最优
这个最优的定义是相对的,并不好维护。能够降低它的复杂度意味着还有别的性质。

d p \mathcal{dp} dp能够有的特殊性质倒不多,可以考虑到的比如说决策单调性?
决策单调性也就是说比如现在 a &lt; b &lt; c &lt; d \mathcal{a&lt;b&lt;c&lt;d} a<b<c<d
如果用 b \mathcal{b} b来更新 c \mathcal{c} c最优,那么 a \mathcal{a} a更新 d \mathcal{d} d至少不比用 c \mathcal{c} c好。
简单的决策单调性比如单调队列、四边形不等式一类的。
但是这道题目带了一个 G ( i , j ) \mathcal{G(i,j)} G(i,j)

本题的决策单调性可以乱搞瞎蒙意证得到,就不多解释了(
G ( i , j ) \mathcal{G(i,j)} G(i,j)怎么搞?
这么讲可能都比较模糊,我们考虑一下是不是能够用更加直观的形式来表示决策单调性。
我们可以把决策看作多个不同的点,把前面的点更新后面的点的优劣程度看作斜率
为什么这么看?大概脑内模拟一下,维护决策单调性的感觉跟动态维护凸包很像吧?

在维护凸包之前先来讨论一下这个式子要怎么转化成斜率的形式、
i ( x i , y i ) \mathcal{i(x_i,y_i)} i(xi,yi)更新 k ( x k , y k ) \mathcal{k(x_k,y_k)} k(xk,yk)比用 j ( x j , y j ) \mathcal{j(x_j,y_j)} j(xj,yj)更好
首先容易得到 F ( i ) + M + S 2 ( i + 1 , k ) &lt; F ( j ) + M + S 2 ( j + 1. k ) \mathcal{F(i)+M+S^2(i+1,k)&lt;F(j)+M+S^2(j+1.k)} F(i)+M+S2(i+1,k)<F(j)+M+S2(j+1.k)
要转化为 y ( i ) − y ( j ) x ( i ) − x ( j ) ( &lt; / &gt; ) F u n c t i o n O f ( k ) \mathcal{\dfrac{y(i)-y(j)}{x(i)-x(j)}\quad(&lt;/&gt;)\quad FunctionOf(k)} x(i)x(j)y(i)y(j)(</>)FunctionOf(k):化式子。过程不难自己推(

先变成 F ( i ) − F ( j ) &lt; [ S ( k ) − S ( j − 1 ) ] 2 − [ S ( k ) − S ( i − 1 ) ] 2 \mathcal{F(i)-F(j)&lt;[S(k)-S(j-1)]^2-[S(k)-S(i-1)]^2} F(i)F(j)<[S(k)S(j1)]2[S(k)S(i1)]2

又变成 F ( i ) − F ( j ) &lt; − 2 S ( k ) S ( j − 1 ) + S 2 ( j − 1 ) + 2 S ( k ) S ( i − 1 ) − S 2 ( i − 1 ) \mathcal{F(i)-F(j)&lt;-2S(k)S(j-1)+S^2(j-1)+2S(k)S(i-1)-S^2(i-1)} F(i)F(j)<2S(k)S(j1)+S2(j1)+2S(k)S(i1)S2(i1)

再变成 F ( i ) + S 2 ( i − 1 ) − F ( j ) − S 2 ( j − 1 ) &lt; 2 [ S ( i − 1 ) − S ( j − 1 ) ] S ( k ) \mathcal{F(i)+S^2(i-1)-F(j)-S^2(j-1)&lt;2[S(i-1)-S(j-1)]S(k)} F(i)+S2(i1)F(j)S2(j1)<2[S(i1)S(j1)]S(k)

最后得到 [ F ( i ) + S 2 ( i − 1 ) ] − [ F ( j ) + S 2 ( j − 1 ) ] S ( i − 1 ) − S ( j − 1 ) &lt; 2 S ( k ) \mathcal{\dfrac{[F(i)+S^2(i-1)]-[F(j)+S^2(j-1)]}{S(i-1)-S(j-1)}&lt;2S(k)} S(i1)S(j1)[F(i)+S2(i1)][F(j)+S2(j1)]<2S(k)
分母(警觉) 小心不要devided by zero(
那么 y i = F ( i ) + S 2 ( i − 1 ) , x i = S ( i − 1 ) \mathcal{y_i=F(i)+S^2(i-1),x_i=S(i-1)} yi=F(i)+S2(i1),xi=S(i1)
好像成功了(

注意上面提到的这种形式实质上还没有利用到决策单调性;
然而这个时候我们已经可以做初步优化了。
二分查找小于 k \mathcal{k} k的凸集里,斜率 &lt; 2 S ( k ) \mathcal{&lt;2S(k)} <2S(k)且最大的边。
于是就可以用这个边靠后的那个点来更新 k \mathcal{k} k。这个要多一个 l o g \mathcal{log} log

因为显然这道题的 F u n c t i o n O f ( k ) = 2 S ( k ) \mathcal{FunctionOf(k)=2S(k)} FunctionOf(k)=2S(k)显然单调不递减并且x(i)单调
然后就可以单调队列
每次得到 F ( i ) \mathcal{F(i)} F(i)前删掉队头不优于后面一个点的点(边斜率过小);
向凸包中加入 i \mathcal{i} i点前删掉队尾那些会被新凸包包含的点(边斜率过大);
虽然感觉很显然但是这么说起来可能有点奇怪,斜率又要小又不能小的?

也许画个图比较好理解、或者说,
其中第一种情况(边斜率过小)在没有单调性的时候是不能删除然后直接用队头计算 F ( i ) \mathcal{F(i)} F(i)
(至于没有单调性的时候具体要怎么搞上面也说过了,二分)
也就是说第一种情况的删除是对复杂度的优化
所以并不是被限制不能小,而是我们主动把没必要计算的那一部分删除掉;
第二种情况为什么要维护凸壳应该不用多解释大家都是茗白人()
然后就可以写单调队列了。

我不好画图,看大米饼的博客可能比较好懂一点
实际上理解为化成 y = k x + b \mathcal{y=kx+b} y=kx+b m a x / m i n ( b ) \mathcal{max/min(b)} max/min(b)也比较好操作。
比较斜率的部分改成用叉积也是可以的。
代码:卜


总的来说适用范围更广的还是二分,不过多了一个 l o g \mathcal{log} log
对于横坐标都不单调的那些可以搞离线啊搞 c d q \mathcal{cdq} cdq啊搞 S p a l y \mathcal{Spaly} Spaly啦比如 b z o j 1492 \mathcal{bzoj1492} bzoj1492

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值