首页 > 其他分享 >[ARC081F] Flip and Rectangles

[ARC081F] Flip and Rectangles

时间:2022-10-23 10:26:21浏览次数:50  
标签:ch int void Flip template inline Rectangles ARC081F getchar

考虑转换题目给出的条件。
可以观察到一些性质

  • 若某个矩形能被操作为全 \(1\) ,那么其任意子矩形也一定可以。
  • 任意行列交换不影响矩阵是否能变为全 \(1\)
    然后重要的来了 任选位置 \([x,y]\) 强制使 \(A[x,y]\) 变为 \(1\), 不是则取反整个矩阵。然后查看第 \(x\) 行第 \(y\) 列,若有一个数为 \(0\) 则翻转对应列/行。之后再做任何操作都会破坏原本第 \(x\)
    行第 \(y\) 列的 \(1\)。

这等价于,对于位置 \(A[i,j]\) \((i \not= x, j \not= y)\),检查 \(!A[x,y], !A[i,y], !A[x,j], A[i,j]\) 的异或值是否为 \(1\)。

也即对于位置 \(A[i,j]\) \((i \not= x, j \not= y)\),检查 \(A[x,y], A[i,y], A[x,j], A[i,j]\) 的异或值是否为 \(0\)。

由于 \([x, y]\) 也是任选的, 所以任意一个子矩形内部四角异或和为 \(0\)。 同时这也充要。

在转化充要条件时,判定算法可能是构造性的。此时要尽量多想“有没有其他方法也可以完成构造?”,以得到更多性质。
比方说,在本题中,若直接选择第一行第一列开始构造(而不是任意的 \([x,y]\))就很难得到这个性质。

然后根据这个条件不难推知,只要矩形内部任意一个 \(2\times 2\) 的矩阵满足条件即可。
那么本问题就被转化为最大全 \(1\) 子矩阵问题。悬线法解决即可。

#include<bits/stdc++.h>
#define RG register
#define LL long long
#define U(x, y, z) for(RG int x = y; x <= z; ++x)
#define D(x, y, z) for(RG int x = y; x >= z; --x)
#define update(x, y) (x = x + y >= mod ? x + y - mod : x + y)
using namespace std;
void read(){}
template<typename _Tp, typename... _Tps>
void read(_Tp &x, _Tps &...Ar) {
	x = 0; char ch = getchar(); bool flg = 0;
	for (; !isdigit(ch); ch = getchar()) flg |= (ch == '-');
	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	if (flg) x = -x;
	read(Ar...);	
}
inline char Getchar(){ char ch; for (ch = getchar(); !isalpha(ch); ch = getchar()); return ch;}
template <typename T> inline void write(T n){ char ch[60]; bool f = 1; int cnt = 0; if (n < 0) f = 0, n = -n; do{ch[++cnt] = char(n % 10 + 48); n /= 10; }while(n); if (f == 0) putchar('-'); for (; cnt; cnt--) putchar(ch[cnt]);}
template <typename T> inline void writeln(T n){write(n); putchar('\n');}
template <typename T> inline void writesp(T n){write(n); putchar(' ');}
template <typename T> inline void chkmin(T &x, T y){x = x < y ? x : y;}
template <typename T> inline void chkmax(T &x, T y){x = x > y ? x : y;}
template <typename T> inline T Min(T x, T y){return x < y ? x : y;}
template <typename T> inline T Max(T x, T y){return x > y ? x : y;}
inline void readstr(string &s) { s = ""; static char c = getchar(); while (isspace(c)) c = getchar(); while (!isspace(c)) s = s + c, c = getchar();}
inline void FO(string s){freopen((s + ".in").c_str(), "r", stdin); freopen((s + ".out").c_str(), "w", stdout);}

const int N = 2e3 + 10;
int n, m, l[N][N], r[N][N], up[N][N];
char a[N][N];

int main(){
	//FO("");
	read(n, m);
	int ans = max(n, m);
	U(i, 1, n) {
		scanf("%s", a[i] + 1);
		U(j, 1, m) a[i][j] = (a[i][j] == '#');
	}
	--n, --m;
	U(i, 1, n) U(j, 1, m) {
		a[i][j] = !(a[i][j] ^ a[i + 1][j] ^ a[i + 1][j + 1] ^ a[i][j + 1]);
		l[i][j] = r[i][j] = j;
	}

	U(i, 1, n) {
		U(j, 2, m) if (a[i][j] && a[i][j - 1]) l[i][j] = l[i][j - 1];
		D(j, m - 1, 1) if (a[i][j] && a[i][j + 1]) r[i][j] = r[i][j + 1];
		U(j, 1, m) {
			// cerr << int(a[i][j]) << " ";
			if (a[i][j]) {
				if (a[i - 1][j]) {
					chkmax(l[i][j], l[i - 1][j]);
					chkmin(r[i][j], r[i - 1][j]);
				}
				up[i][j] = up[i - 1][j] + 1;
				// cerr << up[i][j] << " " << i << " " << j << "\n";
				// if (i == 3 && j == 3) {
					// cerr << l[i][j] << " " << r[i][j] << " " << up[i][j] << "\n";
				// }
				chkmax(ans, (r[i][j] - l[i][j] + 2) * (up[i][j] + 1));
			}
		}
		// cerr << '\n';
	}

	writeln(ans);
	return 0;
}

标签:ch,int,void,Flip,template,inline,Rectangles,ARC081F,getchar
From: https://www.cnblogs.com/SouthernWay/p/16818009.html

相关文章