单调栈求矩形块最大面积 poj 2082 两只黄鹂鸣翠柳,一行白鹭上青天

                                              Terrible Sets

 Let N be the set of all natural numbers {0 , 1 , 2 , . . . }, and R be the set of all real numbers. wi, hi for i = 1 . . . n are some elements in N, and w0 = 0. 
Define set B = {< x, y > | x, y ∈ R and there exists an index i > 0 such that 0 <= y <= hi ,∑ 0<=j<=i-1wj <= x <= ∑ 0<=j<=iwj} 
Again, define set S = {A| A = WH for some W , H ∈ R + and there exists x0, y0 in N such that the set T = { < x , y > | x, y ∈ R and x0 <= x <= x0 +W and y0 <= y <= y0 + H} is contained in set B}. 
Your mission now. What is Max(S)? 
Wow, it looks like a terrible problem. Problems that appear to be terrible are sometimes actually easy. 
But for this one, believe me, it's difficult.

Input

The input consists of several test cases. For each case, n is given in a single line, and then followed by n lines, each containing wi and hi separated by a single space. The last line of the input is an single integer -1, indicating the end of input. You may assume that 1 <= n <= 50000 and w 1h 1+w 2h 2+...+w nh n < 10 9.

Output

Simply output Max(S) in a single line for each case.

Sample Input

3
1 2
3 4
1 2
3
3 4
1 2
3 4
-1

Sample Output

12
14

题意就像诗一样——两只黄鹂鸣翠柳,一行白鹭上青天,不知所云呐!!!

百度是个好东西,经过百度发现题意就是给你几个矩形块求这些矩形块能拼成的最大面积;

样例的图,自己好好想一下就能体会。

解题思路:假如题目给出的矩形正好是按高度单调递增的,很明显我们可以从高到低枚举所有的矩形块就行了;

比如最高的那一块构成的面积,就是自己的面积;他左边的构成的面积就是他两的宽* 左边那一个的面积;一直这样枚举下去就行了;

对于一般的乱序的矩阵块,就可以维护一个单调增的栈;右边的比左边的高,入栈;否则,把所有比他高的矩形块都出栈;在这个出栈的过程中,记录下这些矩形块能构成的最大面积(这些一定是单调增的),然后合并新的矩形块,最后得到一个单调增的;然后按上述枚举即可,最终答案只需要每次都比较取max;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#define bug puts("hi!")
using namespace std;
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
int n;
int k;
int sum[maxn];
struct node
{
    int w,h;
}a[maxn];
int main()
{
    while(scanf("%d",&n)!=EOF,n!=-1)
    {
        for(int i=0;i<n;++i)
            scanf("%d%d",&a[i].w,&a[i].h);
        stack<node> s;
        int maxarea=0;
        for(int i=0;i<n;++i)
        {
            if(s.empty()) s.push(a[i]);
            else
            {
                if(a[i].h>=s.top().h) s.push(a[i]);
                else
                {
                    int totw=0;
                    while(!s.empty())
                    {
                        ///退栈操作是求比a[i]高的所有矩阵块能构成的最大面积;
                        if(a[i].h<s.top().h)
                        {
                            totw+=s.top().w;
                            int area=totw*s.top().h;
                            maxarea=max(maxarea,area);
                            cout<<maxarea<<endl;
                            s.pop();
                        }
                        else break;
                    }
                    node hh;
                    hh.h=a[i].h;
                    hh.w=a[i].w+totw;
                    s.push(hh);
                }
            }
        }
        int totw=0;
        int toth=0;
        while(!s.empty())
        {
            totw+=s.top().w;
            int area=totw*s.top().h;
            maxarea=max(maxarea,area);
            s.pop();

        }
        cout<<maxarea<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codetypeman/article/details/81559892