動態規劃之單調佇列優化

2021-10-03 02:20:07 字數 1364 閱讀 4533

先上一道單調佇列動態規劃的模板題

這道題很明顯是一道dp題,可以通過兩個for迴圈就能得到結果,但是n,l,r太大了,兩層for迴圈就超時了,所以我們得用單調佇列來優化。

動態規劃一般類如

dp[ i ]=min( dp[ j ] + f(j)) (0 < j < i ),

因為j是從0開始的,使用我們可以用乙個變數記錄dp[ j ] + f(j)的最小值

而dp[ i ]=min( dp[ j ] + f(j)) (i-k< j < i ),則是乙個區間內的,那麼我們不能只用乙個變數去估計它,得用單調佇列。

單調佇列不同於優先佇列,它存的對應陣列的值是單調的,和優先佇列一樣,但是它存的陣列的下標也是遞增的。單調佇列我們可以從隊頭彈出佇列,也可以從隊尾彈出。

比如單調佇列我們維護的是乙個遞減的佇列,那麼我們的隊頭就是區間內最大的,我們用head記為隊頭,tail為隊尾。那麼每次新的變數就和隊尾比較,若新的變數大,那麼我們則不斷把隊尾的元素剔除,最後把元素加進來。對於隊頭來說,如果它已經出了界線,那就把它刪除佇列。

先上一道單調佇列(沒有包含動態規劃)的題

下面是琪露諾的**

因為我們要求的是大於n就行了,所以我們只要求n-right+1到n就行了,因為比如我們跳到n-1,我們還沒大於n,但是我們再跳一次也沒有意義了,因為大於n沒有那個冰凍指數了。

`#include 

#include

#include

#include

using

namespace std;

int a[

200200];

int dp[

200200];

int q[

200200];

int head=

1,tail=

0,cur=0;

intmain()

}for

(int i=n-right+

1;i<=n;i++

) ans=

max(ans,dp[i]);

cout<}}

還有一些題,用到求最大值和最小值,那麼就用兩次(單調遞增,單調遞減)。或者是左邊區間和右邊區間都要求,那麼就正著來一次,反著來一次,分別做標記就行了,如擁擠的奶牛s

最後總結:單調佇列就是把結果先排好,再來用的時候就直接o(1)查詢了,就可以把複雜度o(n^2)降到o(n)了。

單調佇列優化動態規劃

lj 那些又遠又差的,我們就不要了 luogup1725 琪露諾 在幻想鄉,琪露諾是以笨蛋聞名的冰之妖精。某一天,琪露諾又在玩速凍青蛙,就是用冰把青蛙瞬間凍起來。但是這只青蛙比以往的要聰明許多,在琪露諾來之前就已經跑到了河的對岸。於是琪露諾決定到河岸去追青蛙。小河可以看作一列格仔依次編號為0到n,琪...

動態規劃中的單調佇列優化

最近經常出現單調佇列,斜率優化的題目。看到周圍的大神們都會做了,我只能跟上去。要慢慢來,先學單調佇列。類似這樣的轉移方程可以用到單調佇列 f i m ax g j w i 其中,g j 是乙個與i無關係的數。w i 只與i有關係。我們首先開乙個佇列。dp時 1 先刪掉前面超出範圍的隊頭。2 利用隊頭...

hdu 3401 單調佇列優化動態規劃

思路 動態方程很容易想到dp i j max dp i j dp i w 1 j k k ap i dp i w 1 j k k bp i dp i j 表示第i天擁有j個石頭的最大價值。其實每次求得都是最有策略,所有dp i w 1 表示的就是i w 1以前的最優,故不同往前遍歷。那麼主要需要優化...