zjnu1735BOB (單調隊列,單調棧)

Description

Little Bob is a famous builder. He bought land and wants to build a house. Unfortunately, the problem is the
land’s terrain, it has a variable elevation.
The land is shaped like a rectangle, N meters wide and M meters long. It can be divided into N*M squares
(see the image). Bob’s house will be shaped like a rectangle that has sides parallel with the land’s edges and
its vertices coincide with the vertices of the squares. All the land covered by Bob’s house must be of equal
elevation to prevent it from collapsing.

Calculate the number of ways Bob can build his house!

Input

The first line of input contains integers N and M (1 <= N, M <= 1000).
Each of the following N lines contains M integers aij (1 <= aij <= 1000000000), respectively the height of each square of
land.
Warning: Please use faster input methods beacuse the amount of input is very large. (For example, use scanf
instead of cin in C++ or BufferedReader instead of Scanner in Java.)

Output

The first and only line of output must contain the required number from the task statement.

Sample Input

5 3 2 2 2 2 2 1 1 1 1 2 1 2 1 2 1

Sample Output

27

Hint

Clarification of the first example: Some of the possible house locations are rectangles with opposite vertices in (0,0)-
(1,1), (0,0)-(0,2) (height 2) i (2,0)-(2,2), (1,2)-(2,2) (height 1). The first number in the brackets represents the row number

and the second one the column number (0-indexed).


題意:給你一個n*m的矩陣,每一個格子都有自己的價值,讓你在矩陣中找一些格子,使得矩形裏的格子的價值都相同,問最多能找到的矩形數。

思路:如果是普通暴力的話,那麼時間複雜度爲O(n*m*m)爆了,所以要找其他方法。我們可以用單調隊列做(單調棧也可以做的,其實它們兩者的本質是一樣的),這題所要維護的東西和之前求一個平面內的最大矩形面積不同,這裏求的是最多的矩形個數,我們可以先把二維矩陣轉化爲一維,即對於每一行的格子,把上面和它價值相同的格子數作爲它的高度。那麼這個問題就轉化成了有許多長方形格子放在地上,讓你找到包含矩形底的矩形總個數。用單調隊列的時候要維護三個值,q[][0]表示高度,q[][1]表示以它爲右下角格子的矩形個數,q[][2]表示座標,維護一個嚴格遞增單調隊列就行了。


#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 1005
int gra[maxn][maxn],a[maxn][maxn];
int q[1111111][3];

int main()
{
    int n,m,i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                scanf("%d",&gra[i][j]);
                a[i][j]=1;
                if(i>1 && gra[i][j]==gra[i-1][j]){
                    a[i][j]+=a[i-1][j];
                }
            }
        }
        ll cnt=0;
        int front,rear,qidian;
        for(i=1;i<=n;i++){
            gra[i][0]=-1;
            for(j=1;j<=m;j++){
                if(gra[i][j]==gra[i][j-1]){
                    while(front<=rear && q[rear][0]>=a[i][j]){
                        rear--;
                    }
                    rear++;
                    q[rear][0]=a[i][j];q[rear][2]=j;
                    if(rear==1){
                        q[rear][1]=a[i][j]*(j-qidian);  //這裏相當於底*高
                    }
                    else{
                        q[rear][1]=a[i][j]*(j-q[rear-1][2])+q[rear-1][1] ; //這裏要加上隊列裏前一個高度比它低的矩形算出來的符合要求的矩形
                    }
                    cnt+=q[rear][1];
                }
                else{
                    front=1;rear=1;
                    qidian=j-1;
                    q[rear][0]=a[i][j];
                    q[rear][1]=a[i][j];
                    q[rear][2]=j;
                    cnt+=a[i][j];
                }
            }
        }
        printf("%lld\n",cnt);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章