传送门
这题主要是去重,vis[i][j]表示第 vis[i][j] 层 底部为 i,j 左端点为 i 右端点为 j 的极大子矩形是否被选过
若区间{ l[i][j] ,r[i][j] },下方全是 1,则不选
单调栈也可以解这题
#include<bits/stdc++.h>
using namespace std;
const int N = 3e3+10;
int n, m;
char a[N][N];
int u[N][N], l[N][N], r[N][N];
int vis[N][N];
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i]+1;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i][j] == '0') continue;
u[i][j] = a[i-1][j] == '1'?u[i-1][j] : i;
l[i][j] = a[i][j-1] == '1'?l[i][j-1] : j;
}
for(int j = m; j >= 1; j--)
if(a[i][j] == '1')
r[i][j] = a[i][j+1] == '1'?r[i][j+1] : j;
}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i][j] != '1') continue;
if(a[i-1][j] == '1'){
l[i][j] = max(l[i][j], l[i-1][j]);
r[i][j] = min(r[i][j], r[i-1][j]);
}
if(vis[l[i][j]][r[i][j]] == i) continue;
if(l[i+1][j] > l[i][j] || r[i+1][j] < r[i][j] ){
ans++;
vis[l[i][j]][r[i][j]] = i;
}
}
}
cout << ans << endl;
return 0;
}