标签:turn clu height amp 直方图 ram mes 退出 pop
有一个直方图,其所有矩形的底均是1(以后简称小矩形)。给出这些矩形的高度,求这些矩形的并集中存在的面积最大的矩形(简称大矩形)的面积。
大矩形的高必然一边等于一个小矩形的高,另一边小于等于另一个小矩形的高。
我们现考虑面积最大矩形左边高等于其所在小矩形的高的情况,则其右边高小于等于其对应的小矩形的高(以后将此简称为左等高矩形)。我们要维护一个单调栈,使得栈里的矩形的高度都是单调递增的。一个一个枚举小矩形,如果当前小矩形高度比栈顶的矩形高度高或等,则如果所求大矩形是个左边为栈内矩形的左等高矩形,则这条小矩形就必然位于这个大矩形的右边所在小矩形的位置及左侧(性质1)(因为宽度越宽越好)。将此小矩形推入栈中。此情况一直延续到当前小矩形比站定的矩形高度低时。此时如果把此小矩形推入栈内,栈就不满足性质1了。因此这时便是开始利用性质1结算(当前小矩形左方的)左等高矩形的时刻了(小矩形高度乘以到当前小矩形的宽度)。
那么右等高矩形呢?右等高矩形相当于将该大矩形以上部分的小矩形削掉以后的左等高矩形。因此当遇到上述的第二种情况时,当栈顶矩形高度小于当前小矩形高度时,退出,然后将宽度为累加值,高度为当前小矩形高度的矩形推入栈内即可。注意最后要增加一个高度为0的小矩形,来应对大矩形右边为最右一个小矩形的情况。
#include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; const int MAX_N = 100010; int A[MAX_N]; struct Rect { int Height, Width; Rect(int height, int width):Height(height),Width(width){} }; stack<Rect> St; int main() { int n; while (scanf("%d", &n) && n) { for (int i = 1; i <= n; i++) scanf("%d", A + i); long long ans = 0; A[++n] = 0; St.push(Rect(A[1], 1)); for (int i = 2; i <= n; i++) { if (A[i] >= St.top().Height) St.push(Rect(A[i], 1)); else { long long width = 0; while (!St.empty() && St.top().Height >= A[i]) { ans = max(ans, (long long)St.top().Height * (width+=St.top().Width)); St.pop(); } St.push(Rect(A[i], width + 1)); } } printf("%lld\n", ans); } return 0; }
POJ2559 Largest Rectangle in a Histogram 单调队列
标签:turn clu height amp 直方图 ram mes 退出 pop
原文地址:https://www.cnblogs.com/headboy2002/p/9185378.html