HDU 1506 Largest Rectangle in a Histogram(单调栈)
题目大意
给一个直方图,在图中取一个矩形,使其面积最大。
解题思路1
显然对于一个选定的矩形\(S\)来说,其高度取决于所选的直方图矩形中高度最低的那个矩形\(a_i\),换句话说,在选定的面积\(S\)内对于这个高度最低的矩形\(a_i\)来说,没有比它更低的矩形了。所以我们可以用一个矩形,看它能向左向右扩展到哪里,就能得到包括这个矩形\(a_i\)的最大面积\(S\)。至于选定区间的左右端点,可以用单调栈来求出,方法与这道题类似。
代码1
const int maxn = 1e5+10;
int n, arr[maxn], l[maxn], r[maxn];
stack<int> sk, clears;
int main(void) {
while(~scanf("%d",&n) && n) {
for (int i = 1; i<=n; ++i) scanf("%d",&arr[i]);
for (int i = 1; i<=n; ++i) {
while(!sk.empty() && arr[sk.top()]>=arr[i]) sk.pop(); //栈顶是小于当前元素的第一个数的下标
l[i] = sk.empty() ? 1 : sk.top()+1; //因为不包括小于当前元素的数所以右移一个坐标
sk.push(i);
}
sk = clears;
for (int i = n; i>=1; --i) {
while(!sk.empty() && arr[sk.top()]>=arr[i]) sk.pop(); //同上
r[i] = sk.empty() ? n : sk.top()-1; //因为不包括小于当前元素的数所以左移一个坐标
sk.push(i);
}
sk = clears;
ll ans = 0;
for (int i = 1; i<=n; ++i) ans = max(ans, (ll)arr[i]*(r[i]-l[i]+1));
printf("%lld\n",ans);
}
return 0;
}
解题思路2
依然使用单调栈。对于一个连续递增的矩形,很明显,以每个子矩形能够形成的宽度就是他前面的宽度加上他自己的宽度。如果往右边加入一个较低的矩形破坏其单调性,那么这个较低矩形可以形成的宽度就是最左边的比他高的矩形到他的宽度,将中间的矩形弹出,栈依旧具有单调性。
代码2
const int maxn = 1e5+10;
int n, arr[maxn];
stack<P> sk, clears;
int main(void) {
while(~scanf("%d",&n) && n) {
for (int i = 1; i<=n; ++i) scanf("%d",&arr[i]);
ll ans = 0;
arr[n+1] = 0; //用于清空前面的数
for (int i = 1; i<=n+1; ++i) {
int w = 0;
while(!sk.empty() && arr[sk.top().first]>=arr[i]) {
w += sk.top().second;
ans = max(ans, (ll)arr[sk.top().first]*w);
sk.pop();
}
sk.push({i,w+1});
}
sk = clears;
printf("%lld\n",ans);
}
return 0;
}