2019牛客暑期多校訓練營(第二場)H-Second Large Rectangle(二維01矩陣最大矩形)

鏈接:https://ac.nowcoder.com/acm/contest/882/H
來源:牛客網
 

題目描述

給出N*M的二維矩陣,每個位置爲0或1,求其中第二大的全爲1的矩陣的面積,不存在輸出0。

1\leq N,M\leq 1000

輸入

1 2
01

輸出

0

輸入

1 3
101

輸出

1

題目分析:

用O(N*M)的時間處理出每個up[i][j],表示位置(i,j)往上連續的1的數量。

對每一行統計答案貢獻,在每一行中,問題轉換成柱狀圖中的最大矩形問題,白書單調棧經典例題,O(M)可以解決一行,總時間複雜度O(N*M)。

要求的是第二大矩形的面積,只需要在求最大矩形的時候把每個最大矩形刪去一行或刪去一列的1,就能保證次大會被統計到答案中了。

代碼:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 100005;

int n, m;
char s[1005][1005];
int up[1005][1005];

ll res[2];
void update(ll siz) {
    if(siz >= res[0]) {
        res[1] = res[0], res[0] = siz;
    } else if(siz > res[1])
        res[1] = siz;
}

ll L[1005], R[1005];
bool vis[1005][1005];

void getmax(int a[]) {
    stack<int> stk;
    a[0] = a[m + 1] = 0;
    stk.push(0);
    for(int i = 1; i <= m; i++) {
        while(stk.size() && a[stk.top()] >= a[i])
            stk.pop();
        if(stk.size())
            L[i] = stk.top();
        stk.push(i);
    }
    while(stk.size())
        stk.pop();

    stk.push(m + 1);
    for(int i = m; i >= 1; i--) {
        while(stk.size() && a[stk.top()] >= a[i])
            stk.pop();
        if(stk.size())
            R[i] = stk.top();
        stk.push(i);
    }

    typedef pair<int, int> P;
    vector<P>v;
    for(int i = 1; i <= m; i++) {
        ll W = R[i] - L[i] - 1, H = a[i];
        if(vis[L[i]][R[i]] || W == 0 || H == 0)
            continue;
        vis[L[i]][R[i]] = 1;        //打標記防止同一個矩形被計入答案多次
        update(H * W);              //最大
        update(H * W - min(H, W));  //次大
        v.push_back(P(L[i], R[i]));
    }
    for(auto &k : v)
        vis[k.first][k.second] = 0;
}

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%s", s[i] + 1);
    for(int j = 1; j <= m; j++) {
        up[0][j] = 0;
        for(int i = 1; i <= n; i++)
            up[i][j] = s[i][j] == '1' ? up[i - 1][j] + 1 : 0;
    }
    for(int i = 1; i <= n; i++)
        getmax(up[i]);
    printf("%lld\n", res[1]);
    return 0;
}

 

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