感覺我有限的智力難以理解,因此寫下來研究一下(
顧名思義,單調佇列就是乙個佇列內容有單調性的佇列(以下以乙個遞減的單調隊列為例,簡單描述一下如何構造單調佇列:我們可以用單調佇列來維護一列資料中,某長度段連續的子區間中的最大/最小值
例如,給定一串數字,求其每個長度為m的連續子區間的最小值
相較於st表,線段樹等資料結構,單調佇列均攤複雜度o(n),會快很多
在區間往後移動了一位後,我們假定新出現的數字為a
單調佇列的隊首是以前加入的,那麼它可能不在新的區間中,進行判斷是否需要將其刪除
如果a比隊尾的數字小,沒有破壞單調性,我們可以直接把a加入隊尾
如果a比隊尾的數字大,因為a是新加入的數字,它可能在未來的某個區間中成為區間最大值,而在隊中,且比a小的數字一定存在於包含a的區間中,且沒有a大,所以沒用
刪掉完事
這樣我們就構造出了乙個單調佇列
以下** 洛谷:p1886 滑動視窗 /【模板】單調佇列
#include #include #include #include #include #include #include#include#include#includeusing namespace std;
typedef long long ll;
typedef pairp;
int n, k;
struct node
;}que[1000000+5],que2[1000000+5];
int dataa[2000000];
int ans1[1000000+5],ans2[1000000+5];
int main()
for (int i = k - 1; i < n; i++)cout << ans2[i] << ' ';
cout << "\n";
for (int i = k - 1; i < n; i++)cout << ans1[i] << ' ';
}
單調棧就是棧內元素出棧序列單調有序的棧要實現單調棧,我們只需要進行一下操作(以下操作是單調遞增棧,即出棧序列遞增)沒了
我們要想令乙個值a入棧時,首先檢查棧頂元素是否大於a
棧頂元素大於等於a,a可以直接入棧
棧頂元素小於a,一直將棧頂元素出棧,直到棧頂元素大於a,隨後a入棧
ps.我們構造單調棧時,棧內儲存的是元素的下標,而不是元素的值
那麼這玩意有啥用呢(
使用單調棧,我們可以解決諸如尋找數列中某個數之前/後第乙個大於/小於它的數的問題正確性:
我們以尋找某個數前,第乙個大於他的數為例
構造乙個單調遞增的棧,設當前數為a,此時
以下**:洛谷:p5788 【模板】單調棧
#include #include #include #include #include #include #include#include#include#include#include#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pairp;
int n, k;
stacksk;
ll dataa[3000000 + 5];
ll ans[3000000 + 5];
int main()
for (int i = 0; i < n; i++)cout << ans[i]+1 << ' ';
}
單調棧,單調佇列
大多數借鑑了 單調佇列是什麼呢?可以直接從問題開始來展開。poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106,m n 我們知道,解法 在暴力列舉的過程中,有乙個地方是重複比較了,就是在找當前的f i 的時候,i的前面其它m 1個數在算f i 1 ...
單調棧 單調佇列
單調棧 單調佇列是在棧和佇列的基礎上加上單調結構的資料結構。如果乙個元素入棧或入隊,他會檢查之前的元素,如果之前的元素不可能是答案的解,那麼就彈出元素,使得當前元素入棧或入隊。leetcode 239 滑動視窗最大值 此題是單調佇列,每次遇到乙個元素,一直從隊尾彈出,直到隊尾元素大於該元素為止。還需...
單調棧 單調佇列
啊學完了來寫個總結吧 顧名思義,單調,就是指色彩單一某乙個容器裡面的元素都是遞增或遞減的,而單調棧和單調佇列就是這個容器。單調棧 單調棧模板 其他的我就不說了,講下為什麼單調棧是從後往前掃瞄 當我們在判斷乙個數後面第乙個比它大的數時,前提是後面的數已經被處理了,所以我們要從後往前掃瞄。我做了兩種做法...