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;
}