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:

cba927b2484fad94fb5ff7473e9aadef.png

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-即可
当然,求矩形内有几个点一样的容斥定理

这里写图片描述

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

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

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

code:

#include <iostream>
#include <cstdio>
#include <cstring>
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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值