【单调栈】 All-one Matrices

本文解析了牛客网竞赛中的一道关于寻找独立全一子矩阵的问题,通过使用前缀和与栈的数据结构,实现了高效算法。文章详细介绍了算法思路、数据结构选择及其在解决该问题中的应用。

牛客题目链接

https://ac.nowcoder.com/acm/contest/888/A


All-one Matrices

 

Gromah and LZR entered the great tomb, the first thing they see is a matrix of size n\times mn×m, and the elements in the matrix are all 0_{}0​ or 1_{}1​.

 

LZR finds a note board saying "An all-one matrix is defined as the matrix whose elements are all 1_{}1​, you should determine the number of all-one submatrices of the given matrix that are not completely included by any other all-one submatrices".

 

Meanwhile, Gromah also finds a password lock, obviously the password should be the number mentioned in the note board!

 

Please help them determine the password and enter the next level.

输入描述:

 

The first line contains two positive integers n,m_{}n,m​, denoting the size of given matrix.

 

Following n_{}n​ lines each contains a string with length m_{}m​, whose elements are all 0_{}0​ or 1_{}1​, denoting the given matrix.

 

 

1\le n,m \le 30001≤n,m≤3000

输出描述:

Print a non-negative integer, denoting the answer.

示例1

输入

复制

3 4
0111
1110
0101

输出

复制

5

说明

The 5 matrices are (1,2)-(1,4), \; (1,2)-(2,3), \; (1,2)-(3,2), \; (2,1)-(2,3), \; (3,4)-(3,4)_{}(1,2)−(1,4),(1,2)−(2,3),(1,2)−(3,2),(2,1)−(2,3),(3,4)−(3,4)​.

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<string,int> psi;
const int mod=1000000007;
const int INF=1e9+7;
const int maxn=1e5+7;
const double PI=acos(-1);
const int N=3007;
//mat1用于存二维01数组,mat2用于存每列以非0点为开头的前缀和,mat3用于判断当前矩形是否重复
int mat1[N][N],mat2[N][N],mat3[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,m;
    cin>>n>>m;
    //将字符串转换为二维数组
    for(int i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        for(int j=1;j<=m;j++)
        {
            mat1[i][j]=s[j-1]-'0';
        }
    }
    //求前缀和
    for(int j=1;j<=m;j++)
        for(int i=1;i<=n;i++){
            if(mat1[i][j]==0)
                mat2[i][j]=0;
            else
                mat2[i][j]=mat2[i-1][j]+1;
        }
    int cot=0;
    memset(mat3,-1,sizeof(mat3));
    
    for(int i=1;i<=n;i++)
    {
        //栈st1用于存一个递增的序列,栈st2存每个矩形的左区间
        stack<int> st1,st2;
        for(int j=1;j<=m+1;j++)
        {
            int left=j;
            //栈st1非空并且当前值比栈顶元素小
            while(!st1.empty()&&mat2[i][j]<st1.top())
            {
                if(mat3[st2.top()][j]!=i-1) cot++;      //判断是否上一层矩形重复
                mat3[st2.top()][j]=i;
                st1.pop();
                left=st2.top();
                st2.pop();
            }
            //栈st1是空的并且mat2的值大于0,或者栈非空且当前值大于栈顶元素就入栈
            while((st1.empty()&&mat2[i][j])||(!st1.empty()&&mat2[i][j]>st1.top()))
            {
                st1.push(mat2[i][j]);
                st2.push(left);
            }
        }
    }
    cout<<cot<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值