2019牛客多校第八场 A All-one Matrices

链接:https://ac.nowcoder.com/acm/contest/888/A来源:牛客网

题目描述

Gromah and LZR entered the great tomb, the first thing they see is a matrix of size n×mn\times mn×m, and the elements in the matrix are all 0 or 1.

LZR finds a note board saying "An all-one matrix is defined as the matrix whose elements are all 11_{}1, you should determine the number of all-one submatrices of the given matrix that are not completely included by any other all-one submatrices".

Meanwhile, Gromah also finds a password lock, obviously the password should be the number mentioned in the note board!

Please help them determine the password and enter the next level.

输入描述:

The first line contains two positive integers n,mn,m_{}n,m, denoting the size of given matrix.Following nn_{}n lines each contains a string with length mm_{}m, whose elements are all 00_{}0 or 11_{}1, denoting the given matrix.1≤n,m≤30001\le n,m \le 30001≤n,m≤3000

输出描述:

Print a non-negative integer, denoting the answer.

示例1

输入

[复制](javascript:void(0)😉

3 4
0111
1110
0101

输出

[复制](javascript:void(0)😉

5

说明

The 5 matrices are (1,2)−(1,4),  (1,2)−(2,3),  (1,2)−(3,2),  (2,1)−(2,3),  (3,4)−(3,4).

思路

首先考虑每个为 \(1\) 的格子在什么情况下会对答案产生贡献。

易得: 当这个格子为某个极大全1矩形的右下角时会对答案产生贡献。

因此,我们可以枚举每一行作为极大全一矩形的最后一行,对每一列维护前缀和求连续 \(1\) 的数量。

枚举每一个位置时,维护一个严格单调递增的单调栈,并维护最左边可到达的位置。

当点\((i, j)\) 对答案产生贡献时, \((i+1, j)\) 一定为 \(0\) ,并且其 1 的高度小于(i-1, j) 时的高度。

Code

#include <bits/stdc++.h>

using namespace std;
const int maxn = 3010;
typedef pair<int,int> pii;
int mp[maxn][maxn], n, m;

int main() {
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; ++i) {
        for (int j=1; j<=m; ++j)
            scanf("%1d", &mp[i][j]);
    }

    for (int j=1; j<=m; ++j) {
        for (int i=1; i<=n; ++i) {
            if(mp[i][j])
                mp[i][j] = mp[i-1][j]+1;
        }
    }

//    for (int i=1; i<=n; ++i) {
//        for (int j=1; j<=m; ++j)
//            printf("%d", mp[i][j]);
//        puts("");
//    }

    int ans = 0;
    for (int i=1; i<=n; ++i) {
        pii sta[maxn];
        int top=0, r=-1;
        for (int j=1; j<=m+1; ++j) {
            int pos=j;
            while(top && sta[top].first > mp[i][j]) {
                if(sta[top].second <= r) ++ans;
                pos = sta[top--].second;
            }
            if(!mp[i+1][j]) r = j;
            if(mp[i][j] && (!top || sta[top].first<mp[i][j])) sta[++top] = {mp[i][j], pos};
        }
    }
    printf("%d\n", ans);
    return 0;
}

posted @ 2019-08-11 12:57  Acerkoo  阅读(196)  评论(0编辑  收藏  举报