最大全1子矩阵 —— 单调栈

最大全 1 1 1 子矩阵:

模板题:POJ 3494

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,int>;
const int maxn = 2e3 + 5;
int n, m, a[maxn][maxn];
int head, tail, q[maxn];
ll ans;

int main() {
	scanf("%d%d", &n, &m);
	ans = 0;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			scanf("%d", &a[i][j]);
			a[i][j] = a[i][j] ? a[i-1][j]+1 : 0;
		}

	for(int i=1; i<=n; i++) {
		head = 1, tail = 0;
		for(int j=1; j<=m; j++) {
			while(head<=tail && a[i][j]<=a[i][q[tail]]) {
				ll hei = a[i][q[tail]];
				ll wid = j - q[tail-1] - 1;
				ans = max(ans, hei * wid);
				tail--;
			}
			q[++tail] = j;
		}
		while(head <= tail) {
			ll hei = a[i][q[tail]];
			ll wid = m - q[tail-1];
			ans = max(ans, hei * wid);
			tail--;
		}
	}
	printf("%lld\n", ans);
}

次大全 1 1 1 子矩阵:

模板题:2019 牛客多校第2场 H题

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,int>;
const int maxn = 2e3 + 5;
int n, m, a[maxn][maxn];
int head, tail, q[maxn];
char s[maxn];
ll ans1, ans2;

void solve(ll x){
	if(x > ans1) swap(ans1, ans2), swap(x, ans1);
	else if(x > ans2) swap(x, ans2);
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++){
		scanf("%s", s+1);
		for(int j=1; j<=m; j++) {
			a[i][j] = s[j]=='1' ? a[i-1][j]+1 : 0;
		}
	}

	for(int i=1; i<=n; i++) {
		head = 1, tail = 0;
		for(int j=1; j<=m; j++) {
			while(head<=tail && a[i][j]<=a[i][q[tail]]) {
				ll hei = a[i][q[tail]];
				ll wid = j - q[tail-1] - 1;
				solve(hei * wid);
				solve((hei-1) * wid);
				solve(hei * (wid-1));
				tail--;
			}
			q[++tail] = j;
		}
		while(head <= tail) {
			ll hei = a[i][q[tail]];
			ll wid = m - q[tail-1];
			solve(hei * wid);
			solve((hei-1) * wid);
			solve(hei * (wid-1));
			tail--;
		}
	}
	printf("%lld\n", ans2);
}

最大 01 01 01 相间子矩阵:

模板题:P1169 [ZJOI2007]棋盘制作

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
int n, m, mp[maxn][maxn], a[maxn][maxn];
int head, tail, q[maxn];
ll ans, ansq;

int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			scanf("%d", &mp[i][j]);
			a[i][j] = (mp[i][j]^mp[i-1][j]) ? a[i-1][j]+1 : 1;
		}

	for(int i=1; i<=n; i++) {
		int cur = 1;
		while(cur <= m){
			head = 1, tail = 0;
			q[tail] = cur - 1;
			q[++tail] = cur++;
			while(cur<=m && mp[i][cur]!=mp[i][cur-1]){
				while(head<=tail && a[i][cur]<=a[i][q[tail]]) {
					ll hei = a[i][q[tail]];
					ll wid = cur - q[tail-1] - 1;
					ans = max(ans, hei * wid);
					ansq = max(ansq, min(hei, wid) * min(hei, wid));
					tail--;
				}	
				q[++tail] = cur++;			
			}
			while(head <= tail) {
				ll hei = a[i][q[tail]];
				ll wid = cur - q[tail-1] - 1;
				ans = max(ans, hei * wid);
				ansq = max(ansq, min(hei, wid) * min(hei, wid));
				tail--;
			}				
		}
	}
	printf("%lld\n%lld\n", ansq, ans);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值