题目大意:有一个$n imes m$的$01$矩阵,可以把任意行或列反转,问最大的全为一的子矩阵的面积
题解:有一个结论:若一个子矩形$S$中的任意一个$2 imes 2$的子矩形都含有偶数个$1$,则存在一种操作使得$S$中全为$1$。
就令四个点亦或值为$0$的格子(有偶数个$1$)的左上角权值为$1$,求一个最大全$1$子矩形就好了。可以拿单调栈来做
卡点:1.意外交了$python$然后显示$RE$,然后就莫名调了好久
2.$ans$的初值未赋:$ans=max(n,m)$,因为有可能构造出来的矩阵得出的答案不大,但是原矩阵的一行或一列绝对是可以全变成$1$的,所以初值为$max(n,m)$
C++ Code:
#include <cstdio> #include <cstring> #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 ", ans); return 0; }