1. 程式人生 > >單調棧求矩形塊最大面積 poj 2082 兩隻黃鸝鳴翠柳,一行白鷺上青天

單調棧求矩形塊最大面積 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;
}