Codeforces 1200D - White Lines (二维差分)
思路
以行为例,求每一行中存在黑颜色的左边界l和右边界r。那么橡皮擦必须要完全覆盖到这个区间[l, r]才可以使得这一行为白色。那么反过来,如果我们知道这个区间,我们就可以求所有完全覆盖这个区间的橡皮擦所在的位置(是一个矩形范围的区域)。这个区间对这个矩形区域的贡献为1,可以用二维差分。
列也一样这样处理。
#include <bits/stdc++.h>
using namespace std;
const int N = 3e3;
typedef long long ll;
char mp[N][N];
int lie[N][2];
int han[N][2];
int ans[N][N];
int main() {
ios::sync_with_stdio(false);
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++) {
cin >> mp[i] + 1;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(mp[i][j] == 'B') {
han[i][0] = j;
break;
}
}
for(int j = n; j >= 1; j--) {
if(mp[i][j] == 'B') {
han[i][1] = j;
break;
}
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(mp[j][i] == 'B') {
lie[i][0] = j;
break;
}
}
for(int j = n; j >= 1; j--) {
if(mp[j][i] == 'B') {
lie[i][1] = j;
break;
}
}
}
for(int i = 1; i <= n; i++) {
int l = han[i][0], r = han[i][1];
if(l == r && l == 0) {
ans[1][1] += 1;
}
if(r - l + 1 > k) continue;
int x1 = max(1, r - k + 1), y1 = max(1, i - k + 1);
int x2 = l, y2 = i;
ans[y1][x1] += 1;
ans[y2 + 1][x1] -= 1;
ans[y1][x2 + 1] -= 1;
ans[y2 + 1][x2 + 1] += 1;
}
for(int i = 1; i <= n; i++) {
int l = lie[i][0], r = lie[i][1];
if(l == r && l == 0) {
ans[1][1] += 1;
}
if(r - l + 1 > k) continue;
int y1 = max(1, r - k + 1), x1 = max(1, i - k + 1);
int x2 = i, y2 = l;
ans[y1][x1] += 1;
ans[y2 + 1][x1] -= 1;
ans[y1][x2 + 1] -= 1;
ans[y2 + 1][x2 + 1] += 1;
}
int tans = 0;
for(int i = 1; i <= n - k + 1; i++) {
for(int j = 1; j <= n - k + 1; j++) {
ans[i][j] += ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1];
tans = max(ans[i][j], tans);
}
}
cout << tans << endl;
}