佇列元素保持單調遞增(減),而保持的方式就是通過插隊,把隊尾破壞了單調性的數全部擠掉,從而使佇列元素保持單調。
單調佇列的作用 :優化dp。許多單調佇列優化的dp可以使複雜度直接降維,下面就以最簡單的一道題為例:
在某兩座城市之間有 n 個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續 m 個烽火台中至少要有乙個發出訊號。請計算總共最少花費多少代價,才能使敵軍來襲之時,情報能在這兩座城市之間準確傳遞。
sample input
5 3
1 2
5 6
2sample output
分析題目,由於題目要求連續m個烽火台中至少要有乙個發出訊號,
很容易得出dp轉移方程:
f[i]=min(f[j]:i−m那麼怎麼用單調佇列優化呢?
狀態列舉到i,當m=4時,我們要做的就是在i-3到i-1中找到最小的f[j],那麼列舉到i+1時,我們要做的就是要在i-2到i中找到最小的f[j]。上圖中我們可以看出,要尋找最小值的區間向後移動了一位,也就是f[i-m+1]的值被拋棄,f[i-1]的值被加入。這裡就可以用單調佇列處理了,f[i-1]是插隊的資料,f[i-1]有資格插隊是因為它更優且更靠近i,比它更差的數將被它取代,保留那些資料沒有任何好處。而那些已經不再維護區間之外的就不必再對其進行維護,出隊即可。看了**會更加明白:
#include
#include
using
namespace
std;
const
int n = 100000;
int n, m, head = 1, tail = 0, ans = 2147483647;
int a[n + 1], f[n + 1], que[n + 1];
int main()
for (int i = n;i > n - m;i--) //求出答案
ans = min(ans, f[i]);
printf("%d\n", ans);
fclose(stdin);
fclose(stdout);
return
0;}
單調佇列優化dp
形如f i max wi的問題都可以用單調佇列優化。例題 板題 注意乙個地方 求完所有的f後 ans不是f n 而是後面的一段字尾的f 注意字尾的左端點。很顯然是rmq問題 計算字首和sum i 對於固定的右端點 i,我們想讓答案最大等價於max,可以用個單調佇列維護。但是隨便乙個資料結構直接on ...
DP 單調佇列優化
使用單調佇列優化的題目具有這樣的特點,他需要我們維持一段區間內的某個最優值,這個區間是隨著遍歷的順序變化的,但是其變化一定具有這樣的特性,也即維持的區間左右端點一定是單調遞增的,而不能出現回流的現象,否則我們在維持佇列單調性過程中剪枝的資料可能是新的區間中的最大值。維持區間最優值的方法有很多,例如靜...
單調佇列優化DP
這段時間在重溫dp,發現dp中有很大很重要的一塊區域是關於dp優化的,於是來和大家分享一下各種dp優化方法,下面講一下單調佇列優化dp 首先來重溫下什麼是單調佇列,在單調佇列中,每個元素的決策時間單調增而它的決策單調更劣,這就顯然可以明白,最優決策永遠在隊首。如果對上面基礎單調佇列不了解,可以先做 ...