Atcoder Regular Contest 089D Checker

Atcoder Regular Contest 089D Checker


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 or W.
  • 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
4 3
0 1 W
1 2 W
5 3 B
5 4 B
Sample Output 1
4

He can satisfy all his desires by painting as shown in the example above.

Sample Input 2
2 1000
0 0 B
0 1 W
Sample Output 2
2
Sample Input 3
6 2
1 2 B
2 1 W
2 2 B
1 0 B
0 6 W
4 5 W
Sample Output 3
4

每个点,其实就对应着其横纵坐标%(2*k)的点
然后横(纵)(注意是或,不是且,都+k等于没有反色)坐标+k可以反色
这样,我们就可以得到一个(2*k)*(2*k)的矩形,而且它们都要求同色
然后求二维前缀和(容斥定理)
然后O(k^2)枚举矩形
如图,划分为五个区域,另外四个区域直接n-即可
当然,求矩形内有几个点一样的容斥定理

Atcoder Regular Contest 089D Checker_第1张图片

上图整个2k*2k的矩形中所存的点都是一种颜色,所以为了要满足题意,我们只能选择图中黑色或者白色为一种颜色

所以每次枚举计算的个数sum=max(n-sum,sum);

然后枚举矩形图中黑色矩形的位置其实只需要枚举中间黑色小矩形的左上角坐标,其他的通过二维前缀和就都可以表示出来了

code:

#include 
#include 
#include 
using namespace std;
const int K = 3005;
int x[K][K];
int n,k;
int getsize(int x1,int y1,int x2,int y2){
    return x[x2][y2]-x[x2][y1]-x[x1][y2]+x[x1][y1];
}
int main(){
    scanf("%d%d",&n,&k);
    int a,b,i,j;
    char c;
    for(i = 1; i <= n; i++){
        scanf("%d%d %c",&a,&b,&c);
        a %= (2*k);
        b %= (2*k);
        if(c == 'W')
            b += k;
        x[a%(2*k)+1][b%(2*k)+1]++;
    }
    for(i = 1; i <= 2*k; i++){
        for(j = 1; j <= 2*k; j++){
            x[i][j] = x[i][j]+x[i-1][j]+x[i][j-1]-x[i-1][j-1];
        }
    }
    int ans = 0,sum;
    for(i = 1; i <= k; i++){
        for(j = 1; j <= k; j++){
            sum = getsize(0,0,i,j);
            sum += getsize(i,j,k+i,k+j);
            sum += getsize(k+i,k+j,2*k,2*k);
            sum += getsize(k+i,0,2*k,j);
            sum += getsize(0,k+j,i,2*k);
            sum = max(n-sum,sum);
            ans = max(ans,sum);
        }
    }
    printf("%d\n",ans);
    return 0;
}


你可能感兴趣的:(#,思维技巧,#,前缀和)