Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 17105 | Accepted: 5531 |
Description
Input
Output
Sample Input
7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0
Sample Output
8 4000
Hint
题意:柱状图是由一些宽度相等的长方形下端对齐后横向排列得到的图形。现在有由n个宽度为1,高度分别为h1,h2,……,hn的长方形从左到右依次排列组成的柱状图。问里面包含的长方形的最大面积是多少。
分析:如果我们能够预处理出以每个高度为高的长方形的左端点le[i]以及右端点ri[i],那么就可以用O(n)的复杂度扫一遍就可以得到最大值。如何预处理出le[i]以及ri[i]呢?这里就要运用栈的知识点了。先考虑le[i]的情况,定义一个栈head,并且初始化为空。然后不断增加i的值,并且维护这个栈使得它按照下面得顺序存储用于推算后面的le值得元素:
设栈中元素从上到下的值为X(i),则X(i) > X(i+1)且h(X(i)) > h(X(i+1))。
计算ri[i]的时候按照同样的方法求即可。
题目链接:http://poj.org/problem?id=2559
代码清单:
#include<set> #include<map> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<cstdio> #include<string> #include<cctype> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 100000 + 5; int n; ll h[maxn]; ll le[maxn],ri[maxn]; stack<int>head; stack<int>tail; void init(){ while(!head.empty()) head.pop(); while(!tail.empty()) tail.pop(); memset(le,0,sizeof(le)); memset(ri,0,sizeof(ri)); } void input(){ for(int i=1;i<=n;i++) scanf("%I64d",&h[i]); } ll work(){ for(int i=1;i<=n;i++){ while(!head.empty()&&h[head.top()]>=h[i]) head.pop(); if(head.empty()) le[i]=1; else le[i]=head.top()+1; head.push(i); } for(int i=n;i>=1;i--){ while(!tail.empty()&&h[tail.top()]>=h[i]) tail.pop(); if(tail.empty()) ri[i]=n; else ri[i]=tail.top()-1; tail.push(i); } ll res=-1; for(int i=1;i<=n;i++){ res=max(res,h[i]*(ri[i]-le[i]+1)); } return res; } void solve(){ printf("%I64d\n",work()); } int main(){ while(scanf("%d",&n)!=EOF&&n){ init(); input(); solve(); }return 0; }