AtCoder Regular Contest 089 D - Checker 思维题点的转移二维前缀和
Posted ProLightsfxjh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Regular Contest 089 D - Checker 思维题点的转移二维前缀和相关的知识,希望对你有一定的参考价值。
D - Checker
Time limit : 2sec / Memory limit : 256MB
Score : 500 points
Problem Statement
AtCoDeer is thinking of painting an infinite two-dimensional grid in a checked pattern of side K. Here, a checked pattern of side K is a pattern where each square is painted black or white so that each connected component of each color is a K × K square. Below is an example of a checked pattern of side 3:
AtCoDeer has N desires. The i-th desire is represented by xi, yi and ci. If ci is B
, it means that he wants to paint the square (xi,yi) black; if ci is W
, he wants to paint the square (xi,yi) white. At most how many desires can he satisfy at the same time?
Constraints
- 1 ≤ N ≤ 105
- 1 ≤ K ≤ 1000
- 0 ≤ xi ≤ 109
- 0 ≤ yi ≤ 109
- If i ≠ j, then (xi,yi) ≠ (xj,yj).
- ci is
B
orW
. - N, K, xi and yi are integers.
Input
Input is given from Standard Input in the following format:
N K x1 y1 c1 x2 y2 c2 : xN yN cN
Output
Print the maximum number of desires that can be satisfied at the same time.
Sample Input 1
Copy4 3 0 1 W 1 2 W 5 3 B 5 4 B
Sample Output 1
Copy4
He can satisfy all his desires by painting as shown in the example above.
Sample Input 2
Copy2 1000 0 0 B 0 1 W
Sample Output 2
Copy2
Sample Input 3
Copy6 2 1 2 B 2 1 W 2 2 B 1 0 B 0 6 W 4 5 W
Sample Output 3
Copy4
Source
AtCoder Regular Contest 089My 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 <iostream>
#include <cstdio>
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;
Thank you!
------from ProLights
以上是关于AtCoder Regular Contest 089 D - Checker 思维题点的转移二维前缀和的主要内容,如果未能解决你的问题,请参考以下文章
[Atcoder Regular Contest 060] Tutorial
AtCoder Regular Contest E - Or Plus Max