链接:https://ac.nowcoder.com/acm/contest/888/A
来源:牛客网
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.
:求解最大的不被覆盖的子矩阵的个数
这种题目一般需要想到的第一种想法就是枚举!!! 枚举每一行 那么到底枚举什么呢,就枚举以i , j 这个为底的矩形的大小 判断这个矩形能不能被算入答案 , 一个矩形能不能被算作答案的话 那么他需要不能被下面的继承 也就是以我当前矩形为高的这个矩形 我当前最远的左端为pos 右端为j 如果在这段中我下面不是全部都是1 那么我肯定没有被别的覆盖 可以算作答案 但是如果我被再右边的覆盖了怎么办呢 这个时候就需要判断一下,可以利用单调栈来维护这个东西 如果后面的比我当前的高还大 那么就把后面的矩阵给直接入站 当我后面的比我低的话 这个时候就需要考虑是否能够出栈 然后ans++了 如果我pos到j这段下面有0,那么我答案肯定是可以++的 如果没有那么这个肯定是被覆盖了 直接不管 对于加入进来把前面的弹出去的 一定要更新当前的pos等于之前被弹出去的pos,因为的就相当于从大块的继承了一部分过来
最后一个j要等于m + 1 当我前m个都没有完的时候 要进行一次最后的出栈 判断一下当前栈里面有多少个符合情况的 当前的栈里面肯定都是递增的 只需要一个一个判断下面是否有0,记录答案就好了
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define se second
#define fi first
#define pii pair<int,int>
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 3e3 + 10;
const long long int inf = 1e17 + 10;
int h[maxn][maxn];
char mp[maxn][maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
getchar();
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
scanf("%c",&mp[i][j]);
}
getchar();
}
for(int i = 1; i <= m + 1; i++) mp[n + 1][i] = '0';
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
h[i][j] = ( mp[i][j] == '0' ? 0 : h[i - 1][j] + 1 );
}
}
stack<pii> sta;
int ans = 0;
for(int i = 1; i <= n; i++)
{
while(!sta.empty()) sta.pop();
int temp = -1;
int pos;
for(int j = 1; j <= m + 1; j++) // is not enough just add one
{
pos = j;
while(!sta.empty() && sta.top().fi > h[i][j])
{
if(sta.top().se <= temp) ans++;
pos = sta.top().se;
sta.pop();
}
if(mp[i + 1][j] == '0') temp = j; // 最近的0在哪里
if(h[i][j] && (sta.empty() || h[i][j] > sta.top().fi))
{
sta.push(pii(h[i][j],pos));
}
}
//cout<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}