美文网首页
2019牛客第八场A题 (All-one Matrices) 单

2019牛客第八场A题 (All-one Matrices) 单

作者: 叔丁基锂_ | 来源:发表于2019-08-11 18:02 被阅读0次

    题意:给一个01矩阵,求其中极大全1子矩阵的个数,极大指的是这个矩阵不能再往扩展。

    题解:枚举每个子矩阵的底边,维护一个单调栈(严格递增)。

    红色柱子代表栈中元素,蓝色表示即将删除的元素

    如上图所示,栈中维护往上拓展的高度up和以这一块为最右端往左扩展的位置pos。显然pos是左边第一个大于等于自己高度up的值,在push的过程中会一直等于这条柱子自己的位置。此外由于我们考虑的是每个矩阵的底边,而如果当前行的下一行仍然为1,则说明矩阵能往下扩展,跳过这些情况。

    被彩色粗线框起来的是合法矩形

    维护最后一个不能往下扩展的格子ma,每次pop的柱子如果它的pos小于等于ma,则说明我们能找到一个以当前枚举的行为底边的极大子矩阵。

    往上拓展的高度up这个值可以通过类似前缀和的操作预处理。从而总复杂度O(nm)

    #ifdef ONLINE_JUDGE
    #include <bits/stdc++.h>
    #endif
    using namespace std;
    using pii = pair<int, int>;
    const int maxn = 3005;
    char g[maxn][maxn];
    int sum[maxn][maxn];
    
    int main()
    {
        ios::sync_with_stdio(false);
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; I++)
        {
            cin >> (g[i] + 1);
        }
        for (int i = 1; i <= n; I++)
        {
            for (int j = 1; j <= m; j++)
            {
                if (g[i][j] == '1')
                    sum[i][j] = sum[i - 1][j] + 1;
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; I++)
        {
            stack<pii> s;
            int ma = -1;
            for (int j = 1; j <= m + 1; j++)
            {
                int pos = j;
                while (!s.empty() && s.top().first > sum[i][j])
                {
                    if (s.top().second <= ma)
                    {
                        ans++;
                    }
                    pos = s.top().second;
                    s.pop();
                }
                if (!sum[i + 1][j])
                    ma = j;
                if (sum[i][j] && (s.empty() || s.top().first < sum[i][j]))
                {
                    s.emplace(sum[i][j], pos);
                }
            }
        }
        cout << ans << endl;
    }
    

    相关文章

      网友评论

          本文标题:2019牛客第八场A题 (All-one Matrices) 单

          本文链接:https://www.haomeiwen.com/subject/zwpsjctx.html