• 2019牛客暑期多校训练营(第八场)A-All-one Matrices(单调栈+思维)


    >传送门<

    题意:给你一个01矩阵,求出所有不可扩大的全为1的矩阵的个数

    思路:比赛的时候想到了用单调栈,但是也只是想到了,并不知道怎么用,其实和之前求二维01矩阵中全为1的矩阵最大面积非常相像。

    像到什么地步呢!!你想一个不能扩大的矩阵,也即是说不能向左右扩展,也不能向上扩展,那我们就用单调栈维护每一行中每个点能向上扩展的最大高度h。

    目前到这里都和二位01矩阵求最大面积的解法一模一样!!接下来我们只需要判断这个矩阵能不能向下扩展就行了,对吧。这里我们就用数组记录一下,如果能向下扩展就记为1,不能就记为0,最后判断,这个矩阵向左右扩展的最大区间宽度是否大与向下扩展的宽度,如果大与的话就不能向下扩展。

    最后还有一个问题,不知道有没有发现,假如我在同一行两次查找到的矩阵是同一矩阵,那怎么办?

    这个时候就涉及到去重的问题了,仔细观察一下,会发现同一高度的h值在出栈计算得到的矩形是一样的(因为高度相同的肯定能互相扩展),所以高度相同的只用计算一次就好了。我们比较一下弹出的元素和栈顶元素的h值,如果相同就代表高度相同就不能取。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 3005;
    
    int n, m, t, ans;
    int a[maxn][maxn];
    int st[maxn], h[maxn], dn[maxn];
    char c[maxn];
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%s", c+1);
            for (int j = 1; j <= m; j++) a[i][j] = c[j]-'0'; 
        }
        for (int i = 1; i <= n; i++) {
            int t = 0; //t表示栈顶 
            for (int j = 1; j <= m + 1; j++) {
                h[j] = a[i][j] ? h[j] + 1 : 0; //向上能扩展的最大高度 
                dn[j] = dn[j - 1] + a[i + 1][j]; //是某能向下扩展的前缀和 
                while (h[j]<h[st[t]]) {
                    int width = j-1-st[t-1], num = dn[j-1]-dn[st[t-1]]; //width表示能向左右扩展的最大宽度,num表示其中共有几个能够向下扩展 
                    ans += (num<width&&h[st[t-1]]<h[st[t]]); //判断是否满足条件并去重 
                    t--;
                }
                st[++t] = j;
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    为表增加列属性方法探究
    细聊冗余表数据一致性
    缓存架构设计细节二三事
    缓存与数据库一致性保证
    MySQL批量SQL插入性能优化
    Codeforces 1150
    Codeforces 1155
    Codeforces 331D
    Windows & Ubuntu Vscode 配置c++环境
    后缀数组
  • 原文地址:https://www.cnblogs.com/wizarderror/p/11335771.html
Copyright © 2020-2023  润新知