~by Wjvje,2019-5-9
131. 直方图中最大的矩形
直方图是由在公共基线处对齐的一系列矩形组成的多边形。
矩形具有相等的宽度,但可以具有不同的高度。
例如,图例左侧显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为1:
通常,直方图用于表示离散分布,例如,文本中字符的频率。
现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
图例右图显示了所描绘直方图的最大对齐矩形。
输入格式
输入包含几个测试用例。
每个测试用例占据一行,用以描述一个直方图,并以整数n开始,表示组成直方图的矩形数目。
然后跟随n个整数h1,…,hnh1,…,hn。
这些数字以从左到右的顺序表示直方图的各个矩形的高度。
每个矩形的宽度为1。
同行数字用空格隔开。
当输入用例为n=0时,结束输入,且该用例不用考虑。
输出格式
对于每一个测试用例,输出一个整数,代表指定直方图中最大矩形的区域面积。
每个数据占一行。
请注意,此矩形必须在公共基线处对齐。
数据范围
1≤n≤1000001≤n≤100000,
0≤hi≤10000000000≤hi≤1000000000
输入样例:
7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0
输出样例:
8 4000
代码实现:
#include<iostream>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+100;
int Stack[N],Left[N],Right[N];
int a[N];
void solve(int *p, int n)
{
int tot = 0 ;
a[0] = -INF;//stack中存储的是坐标,不是value,这样会简单很多;
Stack[0] = 0;
for(int i=1;i<=n;++i)
{
while(a[Stack[tot]] >= a[i]) tot--;
//找a[i]左边>=它的最远坐标,tot不要放到循环里写,否则易错;
p[i] = Stack[tot] + 1;
Stack[++tot] = i;
}
}
int main()
{
io;
int n;
while (cin >> n , n)
{
for(int i = 1; i <= n; i++)cin>>a[i];//找比a[i]高的半径,维护递增栈;
solve(Left, n);
reverse(a + 1, a + 1 + n);
solve(Right, n);
LL ans = 0; //一定会有解,除非没有矩形,这时候答案为0;
for(int i = 1, j = n; i <= n; i ++, j --)
ans=max(ans, (LL)(n - Right[j] + 1 - Left[i] + 1)*(LL)a[j]);
//ps:现在的a数组是被反转了的;
cout << ans << endl;
}
return 0;
}
The end;