Problem:
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 x_i, y_i and c_i.
If c_i is B, it means that he wants to paint the square (x_i,y_i) black; if c_i is W, he wants to paint the square (x_i,y_i) white.
At most how many desires can he satisfy at the same time?

Constraints

1 ≤ N ≤ 10^5

1 ≤ K ≤ 1000

0 ≤ x_i ≤ 10^9

0 ≤ y_i ≤ 10^9

If i ≠ j, then (x_i,y_i) ≠ (x_j,y_j).

c_i is B or W.

N, K, x_i and y_i are integers.

Input

Input is given from Standard Input in the following format:

N K
x_1 y_1 c_1
x_2 y_2 c_2
:
x_N y_N c_N

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

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text;

public class Program
{

    public void Proc()
    {
        int[] inpt = Reader.ReadLine().Split(' ').Select(a => int.Parse(a)).ToArray();
        int kibouCount = inpt[0];
        CheckLen = inpt[1];
        this.KibouList = new Kibou[kibouCount];
        this.KibouMap = new int[CheckLen * 2, CheckLen * 2];
        this.KibouCountMap = new int[CheckLen * 2, CheckLen * 2];
        for (int i = 0; i < kibouCount; i++) {
            Kibou newKibou = new Kibou(Reader.ReadLine());
            this.KibouList[i] = newKibou;
            this.KibouMap[newKibou.X, newKibou.Y]++;
        }
        for (int i = 0; i < KibouMap.GetLength(0); i++) {
            for (int j = 0; j < KibouMap.GetLength(0); j++) {
                int num = this.KibouMap[i, j];
                if(i>0) {
                    num += this.KibouCountMap[i - 1, j];
                }
                if(j>0) {
                    num += this.KibouCountMap[i, j - 1];
                }
                if(i>0&&j>0) {
                    num -= this.KibouCountMap[i - 1, j - 1];
                }
                this.KibouCountMap[i, j] = num;
            }
        }
        int ans = 0;
        int maxIndex = KibouCountMap.GetLength(0) - 1;
        for (int i = 0; i <=maxIndex; i++) {
            for (int j = 0; j <= maxIndex; j++) {
                int subAns = GetBlockCount(i, j);
                int subX = i + CheckLen;
                int subY = j + CheckLen;
                if(subX>maxIndex) {
                    subX -= this.KibouCountMap.GetLength(0);
                }
                if(subY>maxIndex) {
                    subY -= this.KibouCountMap.GetLength(0);
                }
                subAns += GetBlockCount(subX, subY);
                ans = Math.Max(subAns, ans);
            }
        }
        Console.WriteLine(ans);
    }

    private int GetBlockCount(int x, int y) {
        int maxIndex = KibouCountMap.GetLength(0) - 1;
        int toX = x + CheckLen - 1;
        int toY = y + CheckLen - 1;
        int tmp = GetItemCount(x, y, Math.Min(toX, maxIndex), Math.Min(toY, maxIndex));
        if (toX > maxIndex)
        {
            int subToX = toX - maxIndex;
            int subToY = Math.Min(toY, maxIndex);
            tmp += GetItemCount(0, y, subToX, subToY);
        }
        if (toY > maxIndex)
        {
            tmp += GetItemCount(x, 0, Math.Min(toX, maxIndex), toY - maxIndex);
        }
        if (toX > maxIndex && toY > maxIndex)
        {
            tmp += GetItemCount(0, 0, toX - maxIndex, toY - maxIndex);
        }
        return tmp;
    }

    private int GetItemCount(int fromX, int fromY, int toX, int toY) {
        int ans = KibouCountMap[toX, toY];
        if(fromX>0) {
            ans -= KibouCountMap[fromX - 1, toY];
        }
        if(fromY>0) {
            ans -= KibouCountMap[toX, fromY - 1];
        }
        if(fromX>0&&fromY>0) {
            ans += KibouCountMap[fromX - 1, fromY - 1];
        }
        return ans;
    }


    private int[,] KibouMap;
    private int[,] KibouCountMap;
    private Kibou[] KibouList;
    private class Kibou {
        public long X;
        public long Y;
        public Kibou(string inpt) {
            string[] tmp = inpt.Split(' ');
            this.X = long.Parse(tmp[0]);
            this.Y = long.Parse(tmp[1]);
            if(tmp[2][0]=='W') {
                this.X += CheckLen;
            }
            this.X = this.X % (CheckLen * 2);
            this.Y = this.Y % (CheckLen * 2);
            if (this.X >= CheckLen && this.Y >= CheckLen) {
                this.X -= CheckLen;
                this.Y -= CheckLen;
            }
        }
    }

    public static int CheckLen;


    public class Reader
    {
        private static StringReader sr;
        public static bool IsDebug = false;
        public static string ReadLine()
        {
            if (IsDebug)
            {
                if (sr == null)
                {
                    sr = new StringReader(InputText.Trim());
                }
                return sr.ReadLine();
            }
            else
            {
                return Console.ReadLine();
            }
        }
        private static string InputText = @"





2 1000
0 0 B
0 1 W


";
    }

    public static void Main(string[] args)
    {
#if DEBUG
        Reader.IsDebug = true;
#endif
        Program prg = new Program();
        prg.Proc();
    }
}