牛客第八场 A All-one Matrices —— 单调栈

题目链接:点我啊╭(╯^╰)╮

题目大意:

    求不可扩大的全 1 1 1 子矩阵的个数

解题思路:

    发现与最大全 1 1 1 子矩阵很像
    最大全 1 1 1 子矩阵在出栈的过程中,确保了向左向右和向上不可扩展
    那么只需要在处理一下向下不可扩展即可

    记录下一行的 0 0 0 的前缀和
    只需要出栈元素所影响范围内的下一行有 0 0 0 即为向下不可扩展即可
    注意要处理重复元素和清空栈

核心:最大全1子矩阵的灵活运用

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const ll mod = 1e9 + 7;
const int maxn = 3e3 + 10;
int n, m, q[maxn];
char a[maxn][maxn];
int h[maxn][maxn], num[maxn][maxn];
ll ans;

int main() {
	scanf("%d%d", &n, &m);
	getchar();
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			scanf("%c", &a[i][j]);
			h[i][j] = (a[i][j]-'0') ? h[i-1][j] + 1 : 0;
			num[i][j] = num[i][j-1] + (!(a[i][j]-'0'));
		}
		getchar();
	}
	for(int i=0; i<=m; i++) num[n+1][i] = i;
	for(int i=1; i<=n; i++){
		int head = 1, tail = 0;
		q[++tail] = 0;
		for(int j=1; j<=m; j++){
			while(head<=tail && h[i][j]<h[i][q[tail]]) {
				int l = q[tail-1] + 1;
				int r = j - 1;
				int cnt = num[i+1][r] - num[i+1][l-1];
				if(cnt) ans++;
				tail--;
			}
			if(h[i][j] == h[i][q[tail]]) q[tail] = j;
			else q[++tail] = j;
		}
		while (head < tail){
			int l = q[tail-1] + 1;
			int r = m;
			int cnt = num[i+1][r] - num[i+1][l-1];
			if(cnt) ans++;
			tail--;
		}
	}
	printf("%lld\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值