<span>2019牛客暑期多校训练营(第八场)A 单调栈</span>

题意

给一个\(n*m\)的01矩阵,找有多少个全1子矩阵不被其他全1子矩阵包括。

分析

用单调栈找到的全1子矩阵是不能向上扩展和向右扩展的,只需判断该子矩阵能否向左和向下扩展,若四个方向都不能扩展,则该矩阵合法。是否能向左扩展可用预处理出的左边一列的高度是否大于等于该子矩阵的高度判断,是否能向下扩展可用前缀和判断下面一段是否全1。

Code

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=1e9+7;
const int maxn=1e5+10;
int n,m;
int a[3010][3010],h[3010][3010],sum[3010][3010];
int l[3010],r[3010],sta[3010],ans;
void solve(int R){
    int top=0,cur;
    for(int j=1;j<=m+1;j++){
        cur=sta[top];
        while(top&&h[R][cur]>h[R][j]){
            r[cur]=j-1;
            --top;
            cur=sta[top];
        }
        l[j]=cur+1;
        sta[++top]=j;
    }
    for(int j=1;j<=m;j++){
        if(a[R][j]&&sum[R+1][r[j]]-sum[R+1][l[j]-1]!=r[j]-l[j]+1&&h[R][l[j]-1]<h[R][j]) ans++;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%1d",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]) h[i][j]=h[i-1][j]+a[i][j];
            sum[i][j]=sum[i][j-1]+a[i][j];
        }
    }
    for(int i=1;i<=n;i++) solve(i);
    printf("%d\n",ans);
    return 0;
}
全部评论

相关推荐

恰好,我就是有一个弟弟。这样的关注让我感到有些无奈,难道这和我的能力、经验有什么关系吗?求职的路上,真是充满了各种奇怪的考量,让我很想吐槽。希望未来的招聘能更关注求职者的专业素养,而不是这些无关紧要的个人信息。
热血的蚊不叮追赶太阳:找工作,你就是牛马,牛马是否便宜,是否好压迫,女的牛马生不生孩子,男的牛马有没有房贷,一切都是试探你是否好压榨,所以真的我看你是汽车行业的,可以去外企博世,舍弗勒,索恩格,大陆。。。各种外企的供应链 甚至麦当劳苹果店长这些我感觉都把人当人看
点赞 评论 收藏
分享
11-24 19:04
已编辑
湖南工商大学 Java
点赞 评论 收藏
分享
12-10 19:11
重庆大学 Java
香梨想要offer:一样啊朋友,我也是被驳回了,真的挺让人无语的,为什么不一开始就挂了算了,内耗我这么多天。如果华为给每个人造成的内耗能汇聚起来,该是多大一股能量
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务