版权声明:大鹏专属 https://blog.csdn.net/NCC__dapeng/article/details/88294967
一道从来没见过的单调栈题目,先来一篇大佬有关于单调栈的详解。
题目大意:让你选出图表中面积最大的矩形。
思路:在刚看完单调栈的详解后,自己也试了试做这道题,但是仍然没有思路,包括看完题解之后脑子一片混沌,不明白这是怎么和单调栈扯上关系的,反复思考了许多遍代码之后才有了一点心得,在这里与大家分享(具体题目的思路在上面的详解中有)。
首先这道题我们需要先规定一个标准,枚举每个点,只要遇到比自己就要终止,遇到比自己大的就继续迭代。
个人人文单调栈的本质其实就是存取,淘汰,迭代,只要订立一个标准让他去工作就可以。
这里分析这道题的第一个例子(结合下面给出的AC代码):
PS:第一行代表的是左边界,第二行代表的是右边界。
我们直接看数据中的4,他的左边界是2,有边界是4,然后我们在看2是怎么得出的,2代表数组中的位置1所代表的位置,有边界4是数组中位置4所代表的位置,所得出的结果正确。
但是由于我们的平常思维都是想办法确定一个确定位置然后再去分散,所以可能不是很理解,这就是单调栈的迭代问题,这里起作用的就是我们上面所立的标准,凡是比自己小的一律结束然后我们可以发现,自己左右两边的值都大于自己并且最接近自己的值,而自己则是中间的最小值。
(可能介绍的有点乱,但是还是希望自己能多出样例多理解,单调栈十分重要)
下面给出AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
stack<int> s;
ll a[maxn],l[maxn],r[maxn];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(int i=0; i<n; i++) scanf("%lld",&a[i]);
while(!s.empty()) s.pop();
for(int i=0;i<n;i++)
{
while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
if(s.empty()) l[i]=0;
else l[i]=s.top()+1;
s.push(i);
}
while(!s.empty()) s.pop();
for(int i=n-1;i>=0;i--)
{
while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
if(s.empty()) r[i]=n;
else r[i]=s.top();
s.push(i);
}
for(int i=0;i<n;i++) printf("%d ",l[i]);
printf("\n");
for(int i=0;i<n;i++) printf("%d ",r[i]);
printf("\n");
ll ans=0;
for(int i=0;i<n;i++)
{
ans=max(ans,a[i]*(r[i]-l[i]));
}
printf("%lld\n",ans);
}
return 0;
}