http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
收藏
关注
有一个正整数的数组,化为直方图,求此直方图包含的最大矩形面积。例如 2,1,5,6,2,3,对应的直方图如下:
面积最大的矩形为5,6组成的宽度为2的矩形,面积为10。
Input
第1行:1个数N,表示数组的长度(0 <= N <= 50000) 第2 - N + 1行:数组元素A[i]。(1 <= A[i] <= 10^9)
Output
输出最大的矩形面积
Input示例
6 2 1 5 6 2 3
Output示例
10
以前用迭代处理然后dp的作法,复杂度是O(NlogN),现在才知道可以用单调栈达到O(N)的线性作法,很巧妙。
很明确的做法是对于每一个矩形,向左右延伸至无法延伸然后计算更新最大值,朴素作法确实费时;
我们维护一个高度递增的单调栈,如果当前a[i]比栈顶元素的高/相等就一直push,直到遇见高度小于栈顶元素高度时候,说明前面部分矩形的右端点最大只能到这了,因为高度不够了,
接着我们就不断的提出栈顶元素,将他作为左端点,第一个出栈顶元素作为右端点更新最大值,直到栈空了或者栈顶元素不再>=a[i],退出pop操作。
然后将ai加入栈顶,注意宽度是1+所有出栈元素宽度和,因为前面小于这些元素高度的矩形还是能穿过他们的。
1 #include <iostream> 2 #include<algorithm> 3 #include<stack> 4 #include<cstdio> 5 using namespace std; 6 typedef long long LL; 7 struct node{ int h, w; }; 8 int main() 9 { 10 int N, i, j, k, a; 11 stack<node>S; 12 scanf("%d", &N); 13 LL ans = 0; 14 for (i = 1;i <= N;++i) 15 { 16 scanf("%d", &a); 17 if (S.empty() || S.top().h <= a) S.push(node{a,1}); 18 else { 19 int w = 0; 20 while (!S.empty() && S.top().h > a) { 21 w += S.top().w; 22 ans = max(ans,(LL)S.top().h*w); 23 S.pop(); 24 } 25 S.push(node{a,w+1}); 26 } 27 } 28 int w = 0; 29 while (!S.empty()) { 30 w += S.top().w; 31 ans = max(ans,(LL)S.top().h*w); 32 S.pop(); 33 } 34 printf("%lld ", ans); 35 return 0; 36 }