題目描述
n<=500000 , m<=1000。
基本思路
根據題目,我們可以列出dp[i]=dp[j]+(a[i]-a[j])2+m,其中dp[i]表示i點是最後一段的最後乙個數字的最小花費,a[j]是字首和。但是這個dp式顯然是o(n2)的,我們考慮怎麼對它進行優化,化簡得:
dp[i]=dp[j]+a[i]2+a[j]2-2*a[i]*a[j]+m
由於這個dp式在計算時需要a[i]和a[j]的乘積,單調佇列就不能維護了。
斜率優化
半年多沒接觸,都不知道怎麼用它了……
接下來有一些玄學推導:
設用j更新比k更優,則:
dp[j]+a[i]2+a[j]2-2*a[i]*a[j]+m2+a[k]2-2*a[i]*a[k]
消去同類項:dp[j]+a[j]2-2*a[i]*a[j]2-2*a[i]*a[k]
移項:dp[j]-dp[k]+a[j]2-a[k]2
<2*a[i]*(a[j]-a[k])
我們設f[j]=dp[j]+a[j]2,f[k]=dp[k]+a[k]2
d p[
j]−a
[k]a
[j]−
a[k]
\frac
a[j]−a
[k]d
p[j]
−a[k
]<2*a[i]
這個東西……是不是很像斜率
哈!這就是它為什麼要叫斜率優化。
具體實現
其實最重要的東西我都講了,我們可以用這個式子結合單調佇列維護凸包,就能過了。
看**吧。
#include
#define ll long long
const ll maxn =
500005
;ll read()
ll n,m,a[maxn]
,q[maxn]
,dp[maxn]
;ll slope_up
(ll j,ll k)
ll slope_down
(ll j,ll k)
intmain()
printf
("%lld\n"
,dp[n]);
}}
注:本篇題解只是斜率優化入門,沒有深究,後面做到難題時再補幾發部落格吧 HDU3507 斜率優化
r 題意 把n分成任意段 每段中連續 每一段代價 ci m 求總的最小代價 i l作為提醒自己的經驗題,即使再水也要記住坑點 其實是自己被坑的地方 斜率優化裸題 首先定義dp i 表示把前i個處理好的最小代價 dp i min 一看這個轉移就是n 2的,我們來搞成o n 的。h i m sum i ...
hdu 3507 斜率優化
我的第一道斜率優化。就這道題而言,寫出原始的方程 dp i min o n 2 的複雜度肯定超時,要麼優化轉移,要麼重寫方程。斜率優化的思想就是減少不必要的列舉 即不列舉肯定不會成為決策點的j 我們考慮兩個位置p 選擇q比選擇p優 當且僅當 dp q sum i sum q 2 m dp p sum...
hdu3507斜率優化dp
這題 n可能取500000,o n 2 就會超時吧,所有只能優化。注意到這題的動態規劃方程 dp i max dp j sum i sum j 2 m 化簡下得 dp i max dp j sum i 2 sum j 2 2 sum i sum j 無法直接用單調佇列優化,i和j不能分開。假設j比k...