• [AT2699]Flip and Rectangles


    题目大意:有一个$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;
    }
    
  • 相关阅读:
    题库重整
    计算几何练习题――直线交点
    An Easy Task
    简单排序
    IBM Minus One
    Binary Numbers
    去掉VS2010代码中文注释的红色下划线
    【转】Windows socket基础
    【STL】vector的insert方法详解
    window7下 cocos2dx android交叉编译环境部署小结
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9640201.html
Copyright © 2020-2023  润新知