learning 單調佇列與單調棧用法詳解

2022-05-03 19:15:09 字數 1230 閱讀 8939

1、單調棧

單調棧是指乙個棧內部的元素具有嚴格單調性的一種資料結構,分為單調遞增棧和單調遞減棧。

其具有以下兩個性質:

1,滿足棧底到棧頂的元素具有嚴格單調性。

2,滿足棧的先進後出特性,越靠近棧頂的元素越後出棧。

元素進棧過程:

對於乙個單調遞增棧來說,若當前進棧的元素為a,如果a《棧頂元素,則直接將a進棧。

如果a≥棧頂元素,則不斷將棧頂元素出棧,直到滿足a《棧頂元素。

模擬乙個數列構造乙個單調遞增棧

進棧元素分別為3,4,2,6,4,5,2,3。

所示過程即為進棧過程。

實現單調棧stl棧和手寫棧均可。

2,單調佇列。

單調佇列與單調棧及其相似,把單調棧先進後出的性質改為先進先出既可。 

元素進佇列的過程對於單調遞增佇列。

對於乙個元素a,如果a>隊尾元素,那麼直接將a扔進佇列,如果a≥隊尾元素,則將隊尾元素出佇列,直到滿足 a>隊尾元素即可。

實現用stl的雙端佇列即可(我好像一直都是手寫的)

由於雙端佇列即可以在隊頭操作,也可以在隊尾操作,那麼這樣的性質就彌補了單調棧只能在一邊操作的不足。可以使得其左邊也有一定的限制。

3,時間複雜度分析

對於每個元素,其有且僅有一次插入,最多出現一次刪除,故其時間複雜度為o(n)。

練習:給你n個數,讓你在這n個數中選出連續的m個數(m≤n),使這m個數的極差最小,若存在多個區間使得極差均最小,輸出最靠前的區間。

很顯然,$n≤10^4$時暴力明顯可做,$n≤10^6$時通過線段樹也可做,那如果n去到$10^7$呢?

我們考慮用單調佇列維護區間$[i,i+m-1]$的最小值和最大值,以下篇幅以維護最大值舉例。

首先,我們把前m個數扔進乙個單調遞增佇列中,在扔進去的同時把這些數所對應的下邊也扔進去。顯然隊頭的數字即為區間[1,m]最大的數。

考慮基於[1,m]的資料去更新[2,m+1]的最大值。若第乙個數依然存在於佇列中(很顯然若存在僅可能位於隊尾),將這個數刪除,然後將第m+1個數插入改單調佇列。顯然隊尾數字即為區間[2,m+1]的最大值。

重複該過程n-m+1次即可,顯然時間複雜度為o(n)。

練習:bzoj1047

單調佇列與單調棧

單調棧 單調棧,顧名思義,就是維持單調性 遞增或者遞減 的棧結構,如果新入棧的元素破壞了單調性,就彈出原先棧內元素,直到能夠滿足單調性 用途 它可以很方便地求出某個數的左邊或者右邊第乙個比它大或者小的元素,而且總時間複雜度o n 並且單調棧本身並不難實現 維護 每次入棧前先檢驗入棧後是否會破壞棧的單...

單調佇列與單調棧

線段樹等等容易tle,我們需要乙個o n 的演算法來解決這個問題。思路 可以看出,這個視窗是可以用乙個雙向佇列來模擬的,每當後方加入乙個數,都要從佇列尾部開始淘汰掉所有的小於它的數,保證佇列中每乙個數的後面,在視窗範圍內沒有大於等於它的數。當隊首元素不在視窗範圍時,隊首元素出隊。這樣操作後,隊內的元...

單調佇列與單調棧

線段樹等等容易tle,我們需要乙個o n 的演算法來解決這個問題。思路 可以看出,這個視窗是可以用乙個雙向佇列來模擬的,每當後方加入乙個數,都要從佇列尾部開始淘汰掉所有的小於它的數,保證佇列中每乙個數的後面,在視窗範圍內沒有大於等於它的數。當隊首元素不在視窗範圍時,隊首元素出隊。這樣操作後,隊內的元...