[AT2699]Flip and Rectangles

题目大意:有一个$n\times m$的$01$矩阵,可以把任意行或列反转,问最大的全为一的子矩阵的面积

题解:有一个结论:若一个子矩形$S$中的任意一个$2\times 2$的子矩形都含有偶数个$1$,则存在一种操作使得$S$中全为$1$。

就令四个点亦或值为$0$的格子(有偶数个$1$)的左上角权值为$1$,求一个最大全$1$子矩形就好了。可以拿单调栈来做

卡点:1.意外交了$python$然后显示$RE$,然后就莫名调了好久

    2.$ans$的初值未赋:$ans=max(n,m)$,因为有可能构造出来的矩阵得出的答案不大,但是原矩阵的一行或一列绝对是可以全变成$1$的,所以初值为$max(n,m)$

C++ Code:

#include 
#include 
#define maxn 2010
int n, m, ans;
char s[maxn];
int p[maxn][maxn];
inline int max(int a, int b) {return a > b ? a : b;}
struct node {
	int len, h;
	void add(int _a, int _b) {len = _a, h = _b;}
} S[maxn];
int top;
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++) p[i][j] = s[j] == '#';
	}
	for (int i = 1; i < n; i++) {
		for (int j = 1; j < m; j++) {
			if (p[i][j] ^ p[i + 1][j] ^ p[i][j + 1] ^ p[i + 1][j + 1]) p[i][j] = 0;
			else p[i][j] = p[i - 1][j] + 1;
		}
	}
	ans = max(n, m);
	for (int i = 1; i < n; i++) {
		S[++top].add(1, p[i][1]);
		for (int j = 2, len; j < m; j++) {
			len = 1;
			while (top && S[top].h >= p[i][j]) {
				len += S[top].len;
				ans = max(ans, len * (S[top].h + 1));
				top--;
			}
			S[++top].add(len, p[i][j]);
		}
		int len = 1;
		while (top) {
			len += S[top].len;
			ans = max(ans, len * (S[top].h + 1));
			top--;
		}
	}
	printf("%d\n", ans);
	return 0;
}

 

转载于:https://www.cnblogs.com/Memory-of-winter/p/9640201.html

你可能感兴趣的:(c/c++)