單調佇列入門

2022-05-20 11:38:23 字數 2530 閱讀 8530

單調佇列是一種佇列(廢話)

其中佇列的元素保證是單調遞增或者是單調遞減

那麼隊首的元素不就是最小(或最大)的嗎?

我們結合具體的題目來看看吧:

傳送門:p1886 滑動視窗

現在有一堆數字共n個數字(n<=10^6),以及乙個大小為k

的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單

位,求出每次滑動後視窗中的最大值和最小值。

例如:the array is [1 3 -1 -3 5 3 6 7], and k = 3.

輸入一共有兩行,第一行為n,k。

第二行為n個數(輸出共兩行,第一行為每次視窗滑動的最小值

第二行為每次視窗滑動的最大值

輸入樣例#1:

8 31 3 -1 -3 5 3 6 7

輸出樣例#1:

-1 -3 -3 -3 3 3

3 3 5 5 6 7

這裡我們只討論最大值,最小值原理一樣的

如果按照常規方法,我們在求a[i] 即i~i+k-1區間內的最值

時,要把區間內的所有數都訪問一遍,時間複雜度約為

\(o(nk)\)。有沒有乙個快一點的演算法呢?

很明顯,當我們在計算區間\([i-k+1,i]\)的最大值時,是不

是區間\([i-k+1,i-1]\)我們之前已經計算過了?那麼我們

是不是要儲存上一次的結果呢(主要是最大值)?

這時,單調佇列登場——

單調佇列主要有兩個操作:刪頭去尾

**1.刪頭 **

如果佇列頭的元素離開了我們當前操作的區間,那麼這

個元素就沒有任何用了,我們就要把它刪掉

2.去尾

假設即將進入佇列的元素為\(x\),佇列尾指標為\(tail\),

這時我們要比較二者的大小:

1* \(x

此時q仍然保證著遞減性,故直接將\(x\)插入佇列尾

2*\(x>=q[tail]\)

此時,佇列遞減性被打破,此時我們做一下操作:

① 彈出隊尾元素

因為當前的\(q[tail]\)不但不是最大值,對於以後的情況

也不如\(x\)更優,所以要彈出

這好比當前佇列尾部的元素是個能力不足的老兵,而新加入

的新兵更年輕,更能打,當然不要老兵了

②重複執行①,直到滿足\(x或者隊列為空為止

③將\(x\)插入佇列

對於樣例而言:

[1 3 -1] -3 5 3 6 7 

q=,, output:3//分別為每次操作的結果

1 [3 -1 -3] 5 3 6 7

q= output:3

1 3 [-1 -3 5] 3 6 7

q=,, output:5

1 3 -1 [-3 5 3] 6 7

q= output:5

1 3 -1 -3 [5 3 6] 7

q=, output:6

1 3 -1 -3 5 [3 6 7]

q= output:7

由於每個元素最多入隊一次,出隊一次(為什麼?),所以

時間複雜度為\(o(n)\)

當然,這題還可以用st表和線段樹來做,但都沒有單調佇列

方便由於要對隊首和隊尾進行維護,所以我們需要使用

雙端佇列

可以用stl中的deque,也可以手寫

#includeusing namespace std;

int n,m;

int read()

while(ch>='0'&&ch<='9') sum=sum*10+ch-'0',ch=getchar();

return f*sum;

}dequeq;

int a[1000005];

int main()

} printf("\n");

while(!q.empty()) q.pop_front();

for(int i=1;i<=n;i++)

} printf("\n");

return 0;

}

單調佇列是一種小的資料結構,一半不單獨出現,

但是經常我們會遇到單調佇列優化的dp

舉例:noip 2017 pj 第四題 p3957跳房子

二分+dp+單調佇列優化,這裡請大家仔細查閱題解

某年noip tg 的初賽完善程式 烽火傳遞

雖然這題你可以用二叉堆,但明顯單調佇列更好

大家可以看看,這裡我就不講這麼多了

感謝閱讀!

單調佇列 入門

今天寫了人生中第乙個單調佇列,激動ing 先看一道單調佇列的入門題 乙個含有n項的數列 n 2000000 求出每一項前面的第m個數到它這個區間內的最小值。先寫出動規方程 f i min j合法 很明顯的,這是乙個n 2的動規,但是,我們可以注意到,數列中有些數無論如何都不會被選到.如 1 2 8 ...

單調佇列入門

單調佇列這個名字就指明了它的性質 單調性,是乙個單調的雙端佇列 下面列出deque的常用成員函式 來自 單調佇列入門題目 p1886 滑動視窗 模板 單調佇列 這裡我們只討論最大值,最小值原理一樣的 很明顯,當我們在計算區間 i k 1,i 的最大值時,是不是區間 i k 1,i 1 我們之前已經計...

單調佇列入門

給定長度為n的數列a和整數k,求b i min,複雜度為o n 最開始單調隊列為空,保證佇列中的元素始終保持單調性 為了計算b 0 把0到k 1依次加入佇列。在加入i時,當單調佇列的末尾的值j滿足a j a i 則不斷取出。直到雙端隊列為空或者a j a i 之後再於末尾加入i。等到k 1加入佇列,...