1. 程式人生 > >單調隊列與單調棧作用

單調隊列與單調棧作用

序列 bsp 左右 開始 while div tdi 大於 top

單調棧解決的是以某個值為最小(最大)值的最大區間,實現方法是:求最小值(最大值)的最大區間,維護一個遞增(遞減)的棧,當遇到一個比棧頂小的值的時候開始彈棧,彈棧停止的位置到這個值的區間即為此值左邊的最大區間;同時,當一個值被彈掉的時候也就意味著比它更小(更大)的值來了,也可以計算被彈掉的值得右邊的最大區間。

該代碼求以給出的每個值最小(最大)值的最大區間的左右端點。(該區間的每個數嚴格小於它)

#include<iostream>
#include<cstdio>
using namespace std;
const int INF=2147483647,maxn=10000
; int a[maxn+2],top=0,st[maxn+2],l[maxn+2],r[maxn+2],n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); a[n+1]=INF-1;a[0]=INF;st[++top]=0; for(int i=1;i<=n+1;i++) { while(a[i]>a[st[top]]) { l[st[top]]=st[top-1]+1;r[st[top]]=i-1
; top--; } st[++top]=i; } for(int i=1;i<=n;i++)printf("%d %d\n",l[i],r[i]); return 0; }

單調隊列解決的是區間最小(最大)值,實現方法是:求區間最小(最大)值,就維護一個遞增的雙端隊列,隊中保存原始序列的標號,當即將入隊的元素的值比隊尾的元素的值小(大)的時候就不斷彈掉隊尾,知道出現比它更小的值,當即將入隊的元素隊首元素的跨度(即將入隊元素的序號到隊首元素序列的區間)大於規定區間時就不斷彈掉隊首,直到跨度小於或等於所規定的區間。如此可保證隊首元素為最小(最大)值,(但不能保證隊尾就是原始序列中的最大(最小)值),並維護區間長度。

單調隊列與單調棧作用