1. 程式人生 > >單調棧 學習筆記

單調棧 學習筆記

單調棧相對來說比較簡單,那就簡單寫一下。

有些題目的單調棧只是一個“單調的棧”而已,是根據題目的性質維護了一個單調的棧實現一些查詢操作。

但是單調棧更常見的一種用處是維護以每一個點為最大值/最小值的最長的區間是多少。

舉個栗子:1 2 1 1 5
如果要求以每一個點為最小值的區間的話,答案應為[1,5][2,2][1,5][1,5][5,5]

由於每一個點的左右端點都只會被左邊/右邊第一個大於/小於它的點來更新,那麼可以維護一個單增/單減的棧,從前向後和從後向前分別掃一遍,每一次更新右端點或者左端點。

貼一個模板題 BZOJ 1657

#include<iostream>
#include<cstring> #include<cstdio> using namespace std; #define N 50005 int n,h[N],val[N],l[N],r[N],Max,stack[N],top,sum[N],ans; int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d%d",&h[i],&val[i]),l[i]=1,r[i]=n; top=0; for (int i=1;i<=n;++i) { while
(top&&h[stack[top]]<h[i]) { r[stack[top]]=i-1; --top; } stack[++top]=i; } top=0; for (int i=n;i>=1;--i) { while (top&&h[stack[top]]<h[i]) { l[stack[top]]=i+1; --top; } stack
[++top]=i; } for (int i=1;i<=n;++i) sum[l[i]-1]+=val[i],sum[r[i]+1]+=val[i]; for (int i=1;i<=n;++i) ans=max(ans,sum[i]); printf("%d\n",ans); }