D - Checker 思维题、点的转移、二维前缀和
My Solution
题意:用k*k的黑白正方形交替填充二维坐标平面如上图,现给出n个方案(x, y, color表示坐标(x,y)的颜色为color),问最多有多少方案能够同时满足。
思维题、点的转移、二维前缀和
首先要想到把所有的点转移到平面{(0,0)~(k-1,k-1)}内。
1、按照45度向量移动不会改变颜色,
modx = x / k, mody = y / k; x -= min(modx, mody) * k; y -= min(modx, mody) * k;
2、跳动2*k格也不会改变颜色,所以接下来
if(modx > mody) x -= (modx - mody) / 2 * 2 * k; else y -= (mody - modx) / 2 * 2 * k;
3、最后跳动k个需要改变颜色,所以
if(ch == 'W'){
if(x / k) b[x % k][y]++;
else if(y / k) b[x][y % k]++;
else w[x][y]++;
}
else{
if(x / k) w[x % k][y]++;
else if(y / k) w[x][y % k]++;
else b[x][y]++;
}
按照这3个步骤就可以把坐标平面上所以数据的点都转移到平面{(0,0)~(k-1,k-1)}内。
接下来要确定这个平面颜色的分配,可以用一个“十”字来划分区域。
{(0,0)~(i,j)}和{(i+1,j+1)~(k-1,k-1)}为白色,
{(0,j+1)~(i,k-1)}和{(i+1,0)~(k-1,j)}为黑色。
或者
{(0,0)~(i,j)}和{(i+1,j+1)~(k-1,k-1)}为白色,
{(0,j+1)~(i,k-1)}和{(i+1,0)~(k-1,j)}为黑色。
所以需要快速的获取一个矩形区域的数值之和,可以用二维前缀和来表示。
遍历{(0,0)~(k-1,k-1)}内所有的点,
ansb = sumb[i][j] + sumw[k-1][j] - sumw[i][j] + sumw[i][k-1] - sumw[i][j] + sumb[k-1][k-1] - sumb[i][k-1] - sumb[k-1][j] + sumb[i][j];
answ = sumw[i][j] + sumb[k-1][j] - sumb[i][j] + sumb[i][k-1] - sumb[i][j] + sumw[k-1][k-1] - sumw[i][k-1] - sumw[k-1][j] + sumw[i][j];
即可得出答案,ans = max(ans, max(ansb, answ));
时间复杂度 O(K*K)
空间复杂度 O(K*K)
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 1e3 + 8;
int b[MAXN][MAXN], w[MAXN][MAXN], sumb[MAXN][MAXN], sumw[MAXN][MAXN];
int main()
{
#ifdef LOCAL
freopen("b.txt", "r", stdin);
//freopen("b.out", "w", stdout);
int T = 1;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int n, k, i, j, x, y, modx, mody, ansb, answ;
char ch;
cin >> n >> k;
for(i = 0; i < n; i++){ cin >> x >> y >> ch;
modx = x / k, mody = y / k;
x -= min(modx, mody) * k;
y -= min(modx, mody) * k;
if(modx > mody){
x -= (modx - mody) / 2 * 2 * k;
}
else{
y -= (mody - modx) / 2 * 2 * k;
}
//cout << x << " " << y <<" " << ch << endl;
if(ch == 'W'){
if(x / k) b[x % k][y]++;
else if(y / k) b[x][y % k]++;
else w[x][y]++;
}
else{
if(x / k) w[x % k][y]++;
else if(y / k) w[x][y % k]++;
else b[x][y]++;
}
}
for(i = 0; i < k; i++){
for(j = 0; j < k; j++){
if(i == 0){
if(j == 0){
sumb[i][j] = b[i][j];
sumw[i][j] = w[i][j];
}
else{
sumb[i][j] = sumb[i][j-1] + b[i][j];
sumw[i][j] = sumw[i][j-1] + w[i][j];
}
}
else{
if(j == 0){
sumb[i][j] = sumb[i-1][j] + b[i][j];
sumw[i][j] = sumw[i-1][j] + w[i][j];
}
else{
sumb[i][j] = sumb[i-1][j] + sumb[i][j-1] + b[i][j] - sumb[i-1][j-1];
sumw[i][j] = sumw[i-1][j] + sumw[i][j-1] + w[i][j] - sumw[i-1][j-1];
}
}
}
}
//cout << k << endl;
int ans = 0;
for(i = 0; i < k; i++){
for(j = 0; j < k; j++){
// cout << ans << " " << sumb[i][j] + sumw[k-1][k-1] - sumw[i][j] << " " << sumw[i][j] + sumb[k-1][k-1] - sumb[i][j] << endl;
ansb = sumb[i][j] + sumw[k-1][j] - sumw[i][j] + sumw[i][k-1] - sumw[i][j] + sumb[k-1][k-1] - sumb[i][k-1] - sumb[k-1][j] + sumb[i][j];
answ = sumw[i][j] + sumb[k-1][j] - sumb[i][j] + sumb[i][k-1] - sumb[i][j] + sumw[k-1][k-1] - sumw[i][k-1] - sumw[k-1][j] + sumw[i][j];
ans = max(ans, max(ansb, answ));
}
}
cout << ans << endl;
#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}
问题Source
Thank you!
------from ProLightsfx
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
如经许可后转载,请注明出处:https://prolightsfxjh.com/article/atcoder-regular-contest-089-d-checker/
共有 0 条评论