题目链接:点我啊╭(╯^╰)╮
题目大意:
求不可扩大的全 1 1 1 子矩阵的个数
解题思路:
发现与最大全
1
1
1 子矩阵很像
最大全
1
1
1 子矩阵在出栈的过程中,确保了向左向右和向上不可扩展
那么只需要在处理一下向下不可扩展即可
记录下一行的
0
0
0 的前缀和
只需要出栈元素所影响范围内的下一行有
0
0
0 即为向下不可扩展即可
注意要处理重复元素和清空栈
核心:最大全1子矩阵的灵活运用
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const ll mod = 1e9 + 7;
const int maxn = 3e3 + 10;
int n, m, q[maxn];
char a[maxn][maxn];
int h[maxn][maxn], num[maxn][maxn];
ll ans;
int main() {
scanf("%d%d", &n, &m);
getchar();
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%c", &a[i][j]);
h[i][j] = (a[i][j]-'0') ? h[i-1][j] + 1 : 0;
num[i][j] = num[i][j-1] + (!(a[i][j]-'0'));
}
getchar();
}
for(int i=0; i<=m; i++) num[n+1][i] = i;
for(int i=1; i<=n; i++){
int head = 1, tail = 0;
q[++tail] = 0;
for(int j=1; j<=m; j++){
while(head<=tail && h[i][j]<h[i][q[tail]]) {
int l = q[tail-1] + 1;
int r = j - 1;
int cnt = num[i+1][r] - num[i+1][l-1];
if(cnt) ans++;
tail--;
}
if(h[i][j] == h[i][q[tail]]) q[tail] = j;
else q[++tail] = j;
}
while (head < tail){
int l = q[tail-1] + 1;
int r = m;
int cnt = num[i+1][r] - num[i+1][l-1];
if(cnt) ans++;
tail--;
}
}
printf("%lld\n", ans);
}