牛客题目链接
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;
}