2019牛客多校第八场A:All-one Matrices(单调栈 + 思维)

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

解法:我们预处理每个 $1$4的高度以及每一行的前缀和,枚举每一行 $ i$,单调栈求出每个点 j j j h [ i ] [ j ] h[i][j] h[i][j](1的高度)为高度的矩形左边界 L [ j ] L[j] L[j] 和右边界 R [ j ] R[j] R[j] ,然后枚举每个点,如果 s u m [ i + 1 ] [ R [ j ] ] − s u m [ i + 1 ] [ L [ j ] − 1 ] ! = R [ j ] − L [ j ] + 1 sum[i + 1][R[j]] - sum[i + 1][L[j] - 1] != R[j] - L[j] + 1 sum[i+1][R[j]]sum[i+1][L[j]1]!=R[j]L[j]+1,说明这个矩形下面一排不全是 1 1 1,不会被覆盖,答案++,然后我们要去重,可能有多个点 j j j,他们形成的矩形是一模一样的,我们再用一个单调栈(维护单调递增的高度)去一下重,如果栈顶元素高度等于当前点高度,说明是重复的,不用计算。

#include

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

你可能感兴趣的:(数据结构,思维)