标签:
Largest Rectangle in a Histogram
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15831 Accepted: 5121 Description
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.Input
The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow nintegers h1,...,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.Output
For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.Sample Input
7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0Sample Output
8 4000Hint
Huge input, scanf is recommended.Source
/************************************************************************* > File Name: poj_2559.cpp > Author: Howe_Young > Mail: 1013410795@qq.com > Created Time: 2015年04月08日 星期三 09时00分34秒 ************************************************************************/ #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <cstdio> #define INF 99999999999999 using namespace std; typedef long long LL; const int N = 100005; LL h[N], l[N], r[N]; LL Max(LL a, LL b) { return a > b ? a : b; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); int n; while (~scanf("%d", &n) && n) { memset(l, 0, sizeof(l)); memset(r, 0, sizeof(r)); for (int i = 1; i <= n; i++) scanf("%lld", &h[i]); l[1] = 0; h[0] = -1; r[n] = n + 1; h[n + 1] = -1; for (int i = 2; i <= n; i++)//找左边元素 { if (h[i] < h[i - 1]) { int tmp = l[i - 1]; while (h[i] <= h[tmp])//动态规划方法找,如果不用这中方法,普通的tmp--找的话会超时 tmp = l[tmp]; l[i] = tmp; } else if (h[i] == h[i - 1]) l[i] = l[i - 1]; else l[i] = i - 1; } for (int i = n - 1; i > 0; i--)//找右边 { if (h[i] < h[i + 1]) { int tmp = r[i + 1]; while (h[i] <= h[tmp]) tmp = r[tmp]; r[i] = tmp; } else if (h[i] == h[i + 1]) r[i] = r[i + 1]; else r[i] = i + 1; } LL ans = -1; for (int i = 1; i <= n; i++) { h[i] = (r[i] - l[i] - 1) * h[i]; ans = Max(ans, h[i]); } printf("%lld\n", ans); } return 0; }
单调栈的思路是将这些柱子分别一个一个的判断,如果大于前面的那个那么前面比他大的就是0, 所以直接压栈,如果小于的话,弹栈,知道弹出小于它的为止,等于它,弹出来一个,压进去一个。
代码二(单调栈):
/************************************************************************* > File Name: poj_2559_stack.cpp > Author: Howe_Young > Mail: 1013410795@qq.com > Created Time: 2015年04月08日 星期三 09时48分09秒 ************************************************************************/ #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <cstdio> #include <stack> using namespace std; typedef long long LL; const int N = 100005; LL h[N], r[N], l[N]; LL Max(LL a, LL b) { return a > b ? a : b; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int n; while (~scanf("%d", &n) && n) { memset(l, 0, sizeof(l)); memset(r, 0, sizeof(r)); for (int i = 1; i <= n; i++) scanf("%lld", &h[i]); stack<int> S;//找出左边的元素比他大的或者等于它的个数,单调栈 S.push(0);//把额外的一个点压进去,防止栈弹空 h[0] = h[n + 1] = -1; for (int i = 1; i <= n; i++) { if (h[i] < h[i - 1])//如果后者比前者小 { int cnt = 0; while (h[S.top()] >= h[i]) { l[i] += l[S.top()] + 1; S.pop(); } S.push(i); } else if (h[i] == h[i - 1]) { S.pop(); S.push(i); l[i] = l[i - 1] + 1; } else { l[i] = 0; S.push(i); } } stack<int> S2;//找处右边大于等于它的个数 S2.push(n + 1); for (int i = n; i > 0; i--) { if (h[i] < h[i + 1]) { int cnt = 0; while (h[S2.top()] >= h[i]) { r[i] += r[S2.top()] + 1; S2.pop(); } S2.push(i); } else if (h[i] == h[i + 1]) { S2.pop(); S2.push(i); r[i] = r[i + 1] + 1; } else { S2.push(i); r[i] = 0; } } LL ans = -1; for (int i = 1; i <= n; i++) { h[i] *= (l[i] + r[i] + 1); ans = Max(ans, h[i]); } printf("%lld\n", ans); } return 0; }
POJ 2559 Largest Rectangle in a Histogram (单调栈或者dp)
标签:
原文地址:http://www.cnblogs.com/Howe-Young/p/4402304.html