题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1506
思路1:利用单调栈,可以找到从左 / 右遍历第一个比它小 / 大的元素的位置,我们可以用这个性质预处理每一个矩形高度左右边界(也就是第一个比当前高度小的元素的位置),当我们知道左右第一个比它小的数,去掉这两个比它小的,剩下的都是比它大的了,然后就可以用当前这个高度作为矩形的高度求面积,最后取个最大值即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS cin.tie(0); cout.tie(0); ios::sync_with_stdio(0);
const int N = 1e5+7;
int n, a[N], l[N], r[N];
stack <int> s;
int main()
{
IOS;
while(cin >> n && n)
{
while(!s.empty()) s.pop();
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++)
{
while(s.size() && a[i] <= a[s.top()]) s.pop();
if(!s.size()) l[i] = 0;
else l[i] = s.top();
s.push(i);
}
while(!s.empty()) s.pop();
for(int i = n; i >= 1; i--)
{
while(s.size() && a[i] <= a[s.top()]) s.pop();
if(!s.size()) r[i] = n + 1;
else r[i] = s.top();
s.push(i);
}
ll ans = 0;
for(int i = 1; i <= n; i++)
ans = max(ans, (ll)(r[i] - l[i] - 1) * a[i]);
cout << ans << endl;
}
}
/*
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
*/
思路2:维护一个单调递增栈,先在序列两端放两个最小值作为边界,然后遇到比栈顶小的元素就计算栈内元素能够组成的矩形面积并维护最大值即可。此题最小高度为0,所以要用比0小的数作为边界。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 7;
int n, h[N];
stack <int> s;
int main()
{
while(~scanf("%d",&n) && n)
{
for (int i = 1; i <= n; i++)
scanf("%d", &h[i]);
h[0] = -1, h[n+1] = -1;
s.push(0); ll ans = 0;
for(int i = 1; i <= n + 1; i++)
{
while(h[i] < h[s.top()])
{
int index = s.top();
s.pop();
ll tmp = (ll)(i - 1 - s.top()) * h[index];
ans = max(ans, tmp);
}
s.push(i);
}
printf("%lld\n",ans);
}
}