单调栈的模板题
单调栈的定义:
单调递增或单调减的栈,跟单调队列差不多,但是只用到它的一端
1.维护从左往右递增栈可以得到左边第一个比a[i]小的元素位置L[i]。
2.维护从左往右递减栈可以得到左边第一个比a[i]大的元素位置L[i]。
3.维护从右往左递增栈可以得到右边第一个比a[i]小的元素位置R[i]。
4.维护从右往左递减栈可以得到右边第一个比a[i]大的元素位置R[i]。
找一个数左/右边第一个比他大/小的元素的位置。
时间复杂度O(n)。
模板
Stack<int> S;
int a[N], L[N];
for(int i=1 ;i<=n ;i++){
while(S.size() && a[S.top()] >= a[i]) S.pop();//严格单调or非严格?
if(S.empty()) L[i] = 0;
else L[i] = S.top();
S.push(i);
}
例题:HDU - 1506
添加链接描述
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstring>
using namespace std;
const int n=100100;
typedef long long ll;
stack<int>s;
int l[n],r[n];
ll f[n];
int main(){
int m;
while(scanf("%d",&m)!=EOF){
if(m==0)
break;
for(int i=1;i<=m;i++)
scanf("%d",&f[i]);
while(s.size()) //清空栈
s.pop();
for(int i=1;i<=m;i++){
while(s.size()&&f[s.top()]>=f[i])//找到左面第一个比他小的数组的下标
s.pop();
if(s.empty())//如果是空栈了就默认为第一个比他小的数组下标是第一个,这个通过自己画画图就可以知道
l[i]=1;
else
l[i]=s.top()+1;
s.push(i);
}
while(s.size())
s.pop();
for(int i=m;i>=1;i--){
while(s.size()&&f[s.top()]>=f[i])//找到右边第一个比他小的数组下表
s.pop();
if(s.empty())
r[i]=m;
else
r[i]=s.top()-1;
s.push(i);
}
ll ans=0;
for(int i=1;i<=m;i++)
ans=max(ans,f[i]*(r[i]-l[i]+1));
printf("%lld\n",ans);
}
return 0;
}