挑战程序设计的解题思路:
由于每个元素只压入和弹出一次,因此复杂度是O(2N),即O(N)的,同样对于R,也可以用同样的方式求出
自己的理解:以H[i]为一段区间的最小高度,如何求出该区间呢?{以该高度向左右两边依次扩展,以左边为例,左端点L[i]一定是满足H[j]<H[i] (j<i)最大的j,同理,右端点R[i]一定是满足H[j]<H[i] (j>i)最大的j 最后的答案便是max(H[i]*(R[i)-L[i]+1)(0<=i<N) ,这道题用栈来求解L[i]真是太精巧了,首先栈里面的元素一定是递增的,因为是按照序号来的嘛,我一开始有个疑问,为什么弹出的元素对后续比较没有影响呢?原因是:当比较到H[i]时,假设弹出的集合是S,S中的高度值都是大于等于H[i],直到栈顶H[st[t]]的高度是小于H[i]的,才记录结果L[i]=st[t]+1,再将H[i]压入栈中,之后比较H[i+1],如果H[i]>=H[i+1],那么集合S中的高度值显然也会是>=H[i+1],因为S>=H[i]
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pi acos(-1.0)
#define e exp(1.0)
ll N;
const ll maxn=1e5+7;
ll L[maxn],R[maxn],st[maxn],h[maxn];//区间的左端点,区间的右端点,栈,高度
ll solve()
{
ll i,j,t=0;
for(i=0;i<N;i++)//计算L[i]
{
while(t>0&&h[st[t-1]]>=h[i])
t--;
L[i]=t==0?0:st[t-1]+1;
st[t++]=i;
}
t=0;
for(i=N-1;i>=0;i--)//计算R[i]
{
while(t>0&&h[st[t-1]]>=h[i])
t--;
R[i]=t==0?0:st[t-1]-1;
st[t++]=i;
}
ll res=0;
for(i=0;i<N;i++)
res=max(res,h[i]*(R[i]-L[i]+1));
return res;
}
int main()
{
// freopen(".../.txt","w",stdout);
ios::sync_with_stdio(false);
ll i,j;
cin>>N;
for(i=0;i<N;i++)
cin>>h[i];
ll res=solve();
// for(i=0;i<N;i++)
// cout<<L[i]<<" "<<R[i]<<endl;
cout<<res<<endl;
return 0;
}