poj2559(单调栈)

来源:互联网 发布:蓝凌软件股份有限公司 编辑:程序博客网 时间:2024/06/07 02:16

题目链接:http://poj.org/problem?id=2559


Largest Rectangle in a Histogram
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 20199 Accepted: 6489

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.

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 integersh1,...,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 34 1000 1000 1000 10000

Sample Output

84000

Hint

Huge input, scanf is recommended.


尴尬,只会n^2做法,只能水过学校OJ的数据,水不过poj原题,.........

没想到就是没想到,菜得抠脚.......

网上有个比较巧的思路:

使用一个叫“单调栈”的东西

想法很巧妙:将木板从小到大扔进栈中,一旦手里拿的准备进栈的木板(称之为A板)比栈顶的木板还大

就把栈顶的木板拉出来(称之为B板),统计一下面积,与ans比较,存起来最大的,

然后再把栈顶的板拉出来(称之为C板),如果还是小于准备进栈的A板,那么把B板切成C板大小,

统计“两块C板”的面积,与ans比较,存最大(原因:因为栈是单调栈,从小到大存放,那么拉出来的C板肯定比B板小

那么B板肯定可以切成C板大小,那么统计时就有两块C板合成的大板),如此往复......

直到栈顶的板终于不大于A板了,把之前那一堆栈顶弹出,不断切小的板(B板C板等的叠起来的n块板)

切成A板大小,与A板钉在一起扔进栈中,那么此时相当于有 n + 1 块A板合起来的大板(理解为面积)

切成和手里的板的大小相同,在将手里的两块板叠成一块的(理解为面积不变,厚度增加......)

最后把所以栈中的存板全扔出来切,看最多能切成面积多大的板.......

为何能这么干??

首先:单调栈控制栈中板大小递增

其次:一旦手里板小于栈顶板,这意味着没有其他比栈顶板更大的板可以切成栈顶的板,那么面积为栈顶板大小的板只有1块
(这里还有一个前提:“合成板”只能是自身前后相邻的几块组成,不能跳过某块板与其他“合成”)


#include <iostream>#include <algorithm>#include <map>#include <vector>#include <queue>#include <stack>#include <queue>#include <cstdio>#include <string.h>#include <cstdlib>#include <cmath>#include <string>typedef long long ll;#define CLR(a) memset(a, 0, sizeof(a))#define SD(a) scanf("%d", &a)#define FOR(i, a, b)  for(i = a; i < b; i++)#define INF 0x3f3f3f3f#define PI acos(-1.0)#define MAXN 100000 + 10using namespace std;typedef struct{     ll width;     ll height;}Block;Block arr[MAXN];int main(){     int n;     while (~scanf("%d", &n) && n > 0)     {          ll ans = 0;                    stack<Block> blockStack;          for (int i = 0; i < n; i++)          {               scanf("%lld", &arr[i].height);               ll tmp = 0;               while (blockStack.empty() == false && arr[i].height < blockStack.top().height)               {                    ans = max(ans, (blockStack.top().width + tmp) * blockStack.top().height);                    tmp += blockStack.top().width;                    blockStack.pop();               }               arr[i].width = tmp + 1;               blockStack.push(arr[i]);          }          ll tmp = 0;          while (blockStack.empty() == false)          {               ans = max(ans, (blockStack.top().width + tmp) * blockStack.top().height);               tmp += blockStack.top().width;               blockStack.pop();          }          printf("%lld\n", ans);     }     return 0;}




0 0
原创粉丝点击