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 xiyi 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.
  • NKxi 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

Copy
4 3
0 1 W
1 2 W
5 3 B
5 4 B

Sample Output 1

Copy
4

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


Sample Input 2

Copy
2 1000
0 0 B
0 1 W

Sample Output 2

Copy
2

Sample Input 3

Copy
6 2
1 2 B
2 1 W
2 2 B
1 0 B
0 6 W
4 5 W

Sample Output 3

Copy
4

Source

AtCoder Regular Contest 089

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 <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 101

[Atcoder Regular Contest 060] Tutorial

AtCoder Regular Contest 101

AtCoder Regular Contest E - Or Plus Max

AtCoder Regular Contest 146 C Even XOR题解

AtCoder Regular Contest 146 C Even XOR题解