單調棧 學習筆記
阿新 • • 發佈:2018-12-29
單調棧相對來說比較簡單,那就簡單寫一下。
有些題目的單調棧只是一個“單調的棧”而已,是根據題目的性質維護了一個單調的棧實現一些查詢操作。
但是單調棧更常見的一種用處是維護以每一個點為最大值/最小值的最長的區間是多少。
舉個栗子: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);
}