單調棧以及單調隊列
阿新 • • 發佈:2018-09-26
否則 插入 width 項目 ack nss 最小 click https
單調棧:
-
定義:
棧內的元素,按照某種方式排列下(單調遞增或者單調遞減),如果新入棧的元素破壞了單調性,就彈出棧內元素,直至滿足單調性。
-
作用:單調棧可以找到從左/右遍歷第一個比它大/小的元素的位置。時間復雜度為O(N);
-
實現方式:(以維護單調遞增棧為例)
進棧操作:每次進入棧時,先檢驗棧頂元素和進棧元素的大小,如果小於,那麽直接入棧;否則,大於等於進棧元素的出棧,直到棧空或者棧頂元素小於入棧元素。
例如:3 8 2 3 1
- 初始時刻棧為空,3入棧。.....................................棧內元素(3);
- 8要進棧,8比3大,直接入棧。..............................棧內元素(3,8);
- 2要進棧,2比8小,全部彈出,2入棧。.................棧內元素(2);
- 3要進棧,3比2大,直接入棧。..............................棧內元素(2,3);
- 1要進棧,1比3小,全部彈出,1入棧。.................棧內元素(1);
根據此時求出從左往右第一個比它小的元素。
3 8 2 3 1
0 3 0 2 0
代碼:
stack<int>s; forView Code(int i=1;i<=n;i++) { while(s.size()&&s.top()>=a[i]) { s.pop(); } if(s.empty()) l[i]=0; else l[i]=s.top(); s.push(a[i]); }
stack<int>s; for(int i=1;i<=n;i++) { while(s.size()&&s.top()>=a[i]) { s.pop(); }if(s.empty()) l[i]=0; else l[i]=s.top(); s.push(a[i]); }
例題:poj 2559
題意:給出一個柱形統計圖,它的每個項目的寬是1,高度和具體問題有關,現在編輯求出這個柱形圖中的最大面積的長方形(n<=le5)
例如:2,1,4,5,1,3,3
面積為8。
分析:
- 我們首先想到的是逐個考慮每個項目,求出每個項目被包含的長方形。
- 求出每個被包含的長方形,那麽左右兩邊的高度不能比項目本身的高度低,就是向左右兩邊延展。
- 那麽用單調棧,時間復雜度是2N:
- 求出兩邊比項目第一個小的位置。為什麽不是取兩邊比項目第一個大的位置呢?因為如果是大的位置,它們之間可能包含比項目本身要小值,就不能達到連續。
- 分別對項目進行左右延伸。
單調隊列:
-
定義:
隊列中元素之間的關系具有單調性,而且,隊首和隊尾都可以進行出隊操作,只有隊尾可以進行入隊操作。
-
作用:
對於維護好的單調隊列,單調隊列是有序的,那麽取出最大值(最小值)的復雜度是O(1);
可以拿來優化DP;
-
操作:
- 插入:若新元素從隊尾插入後會破壞單調性,則刪除隊尾元素,直至插入後不再破壞單調性為止,在將其插入單調隊列。這和單調棧的插入一樣。
- 獲取最優值:訪問首尾元素。
- 定長連續子區間的最值問題
例題:
題意:給定一個長度為n的數列,求長度為k的定長連續子區間{a1,a2,a3,a4............,ak-1,ak}...............中每個區間的最大值和最小值。
分析:
- 當我們看到這個第一個想法應該是枚舉起始元素ax,然後再求ax到ak-1+x的最大(小)值,那麽區間的復雜度為O(nk);
- al,al+1,al+2....................ar-1,ar,ar+1,以最大值為例:
- 當我們求區間(l,r)最大值時:=max{al,max(al+1,al+2..........ar-1,ar)};
- 當我們求區間(l+1,r+1)最大值時:=max{ar+1,max(al+1,al+2..........ar-1,ar)};
- 那麽再求區間(l+1,r+1)時,我們完全沒必要在重新掃描一次。只有當最值在al才需要重新掃描。
- 那麽如果在區間(l,r)求最大值時,l<i<j<r,如果ai<aj,那麽在向右移動的過程中ai就失去了效果,這就與單調隊列彈出所不符合單調的元素性質一樣。
- 當我們將區間從(l,r)移動到(l+1,r+1)時,我們將ar+1插入單調隊列中,若隊首元素不在(l,r)區間中,那麽說明最大值不是(l,r)區間的數,清除隊首元素(出隊);
例如:4 1 3 2 7 5 6 n=7,k=3;求長度為k的連續子序列的最大值。
- 初始隊列為空,4入隊.....................................................隊列元素(4);
- 進隊元素為1,1比4小,直接入隊...................................隊列元素(4,1);
- 進隊元素為3,3比1大,彈出1,3入隊...........................隊列元素(4,3);那麽最大值為4;
- 進隊元素為2,2比3小,直接入隊...................................隊列元素(4,3,2);因為4不在a2~a4元素中,所有要先彈出4元素,此時最大值為3,隊列元素(3,2);
- 進隊元素為7,7比4大,全部彈出...................................隊列元素(7);此時最大值為7;
- 進隊元素為5,5比7小,直接入隊...................................隊列元素(7,5);此時最大值為7;
- 進隊元素為6,6比5大,彈出5,6入隊...........................隊列元素(7,6);此時最大值為7;
單調棧以及單調隊列