题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1506
Largest Rectangle in a Histogram
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 14310 Accepted Submission(s): 4104
Problem 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.

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 n integers 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 0
Sample Output
8 4000
Source
University of Ulm Local Contest 2003
题目是让你求最大矩阵面积
n<10w,看得出这题是不能暴力的,想来想去,就是已知出当前第i根柱子,从第i根柱子出发,往左往右,求出连续的,并且都比第i根柱子长的柱子根数
刚开始一直纠结于根数的求法, 如果每个i都往左往右暴力枚举,那必然TLE,可是又想不出其他的方法,苦苦思索后换了一个思考角度,求出第i根柱子往左/右,比它高的那根最左/右边的柱子的下标,到时候相减一下就能得出他们的根数了,也就是宽度。答案就是宽度*第i根柱子的高。
求下标的方法是记录祖先点,用l[n],r[n]分别记录当前柱子的左祖先点和右祖先点。例如样例
2 | 1 | 4 | 5 | 1 | 3 | 3 | |
l | 1 | 1 | 3 | 4 | 1 | 6 | 6 |
r | 1 | 7 | 4 | 4 | 7 | 7 | 7 |
代码如下
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXM 100010
int n;
long long mx, s[MAXM], l[MAXM], r[MAXM];
int main()
{
// freopen("input.txt", "r", stdin);
while (scanf("%d", &n) != EOF)
{
if (!n)
break;
for (int i = 1; i <= n; i++)
scanf("%lld", &s[i]);
l[1] = 1;
r[n] = n;
int id;
for (int i = 2; i <= n; i++)
{
id = i;
while (id > 1 && s[i] <= s[id - 1]) //如果id未到边界,并且当前柱子的高度小于等于前一根柱子的高度
id = l[id - 1]; //取前一根柱子的祖先点,也就是比前一根柱子还要高的柱子的下标
l[i] = id; //记录下比当前柱子高的,最左边的那根柱子的下标,也就是得出了当前柱子的祖先点
}
for (int i = n - 1; i >= 1; i--) //当前柱子的右边 同上
{
id = i;
while (id < n && s[i] <= s[id + 1])
id = r[id + 1];
r[i] = id;
}
mx = -1;
for (int i = 1; i <= n; i++)
mx = max(mx, (r[i] - l[i] + 1)*s[i]); //计算面积,遍历一边即可,取最大值
printf("%lld\n", mx);
}
return 0;
}
若实在想不出计算方式,何不换位思考另辟蹊径呢?