题意:问有多少个全1的子矩形,且该矩形不会被另外一个全1子矩形覆盖
解法:我们预处理每个 $1$4的高度以及每一行的前缀和,枚举每一行 $ i$,单调栈求出每个点 以(1的高度)为高度的矩形左边界 和右边界 ,然后枚举每个点,如果 ,说明这个矩形下面一排不全是 ,不会被覆盖,答案++,然后我们要去重,可能有多个点 ,他们形成的矩形是一模一样的,我们再用一个单调栈(维护单调递增的高度)去一下重,如果栈顶元素高度等于当前点高度,说明是重复的,不用计算。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3030;
int mp[maxn][maxn];
signed main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
char cc[maxn];
cin >> (cc + 1);
for (int j = 1; j <= m; j++) {
if (cc[j] == '1')
mp[i][j] = mp[i - 1][j] + 1;
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
stack<pair<int, int> > team;
int ma = -1;
for (int j = 1; j <= m + 1; j++) {
int pos = j;
while (!team.empty() && team.top().first > mp[i][j]) {
if (team.top().second <= ma)
ans++;
pos = team.top().second;
team.pop();
}
if (!mp[i + 1][j])
ma = j;
if (mp[i][j] && (team.empty() || team.top().first < mp[i][j]))
team.push(make_pair(mp[i][j], pos));
}
}
cout << ans << endl;
return 0;
}