POJ 3017 單調佇列 最值優化 的動態規劃

2021-06-09 15:28:51 字數 747 閱讀 2085

令f[i] 表示前i個數按照題目要求的最小的和

則必然有f[i] = min(f[j] + max(a[j +1 , a[j + 2].....a[i])) 

其中j<= i,j的位置還得滿足題目中m 的限制

由於a陣列都是大於0的,所以可以發現f必然是非遞減的。

設a[j + 1], a[j + 2], ...a[i]中值最大的下標為k

設x為[j + 1,k]的任意乙個下標,則a[x],a[x+1],....a[i]的最大值的下標顯然也是k了

由f的非遞減性,f[j+1] + a[k] <= f[j+2]+a[k].....<= f[k - 1] + a[k] 

很顯然,我們只要取f[j+1]+a[k]就可以了。

也就是說如果某一段到當前i位置的最大值都一樣,取最靠前的即可。

如何維護呢,可以聯想到單調佇列。

維護乙個遞減的佇列,存的是符合要求的某一段的最大值,但是可以發現,並不是隊首元素就是最優,因為佇列中的遞減性質,佇列中的所有元素都有可能導致最優解。

這時可以用到的東西就很多了,堆啊,各種樹這樣的。實際上,用個set可以有效的減少**量。

那麼為什麼不用遞增的佇列呢? 如果用遞增,比如佇列中存的是a[1] a[2] a[3]  (a[1]  < a[2] < a[3]) ,現在的位置是x,那麼a[1], a[2] a[3]到x位置的最大值是相等的。那麼a[2]和a[3]就沒有存在的意義了。然後就又變成了遞減的序列。

具體**見

不過30多行就解決問題了。

POJ3017 單調佇列

交的時候沒什麼信心會ac,結果ac了,挺高興的。如果之前能確定演算法沒問題,應該自信點 不熟練還是 題解 先得dp方程 f i f j max x j 1 x j 2 x i 其中j include include include using namespace std typedef int64 ...

poj 3017(單調佇列)

想了半天終於是看的題解,網上的題解好像都是出自一人之手,寫的都一毛一樣,令人窒息。建了乙個遞減的佇列,具體很難講的清,又不想複製別人的講解,就這樣吧。include include include include include include include define ls 2 rt defi...

poj 3017 單調佇列(附加multiset)

只能說是 美如畫。當然我是指內在邏輯不是我的 風格,隊長看到要理解哈,啊哈哈哈哈哈哈哈哈 正常思路咯,f i f j max a j 1 a j 2 a i 列舉j,顯然硬來會超時,所以需要有乙個單調佇列來時時把最大值盡快弄出來並且需要一些剪枝 剪枝條件有兩個,乙個是和不能超過m,乙個是顯然f i ...