51nod 1102 单调栈

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102

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\n", ans);
35     return 0;
36 }

 

posted @ 2017-08-22 11:13  *zzq  阅读(187)  评论(0编辑  收藏  举报