题意:问有多少个全1的子矩形,且该矩形不会被另外一个全1子矩形覆盖

解法:我们预处理每个 $1$4的高度以及每一行的前缀和,枚举每一行 $ i$,单调栈求出每个点 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_i++2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_i++_02(1的高度)为高度的矩形左边界 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_ci_03 和右边界 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_i++_04 ,然后枚举每个点,如果 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_单调栈_05,说明这个矩形下面一排不全是 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_ci_06,不会被覆盖,答案++,然后我们要去重,可能有多个点 2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)_i++,他们形成的矩形是一模一样的,我们再用一个单调栈(维护单调递增的高度)去一下重,如果栈顶元素高度等于当前点高度,说明是重复的,不用计算。

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