#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <array>
#include <cassert>
#include <bitset>
using namespace std;
using LL = long long;

int N, K;

#include <vector>
#include <cassert>
template<typename T>
class imos2d
{
private:
	std::vector<std::vector<T>>buf;
	const int lim1, lim2;
	bool convert;
	inline bool valid(int x, int y, bool wide)
	{
		return (0 <= x && 0 <= y && x < lim1 + (wide ? 1 : 0) && y < lim2 + (wide ? 1 : 0));
	}
	T rawsum(int i1, int i2)
	{
		assert(valid(i1, i2, true));
		return buf[i1][i2];
	}
public:
	//サイズを指定してください
	imos2d(size_t width, size_t height) :
		lim1(width), lim2(height),
		convert(false)
	{
		buf.resize(width + 1, std::vector<T>(height + 1));
	}
	//１マスをマーキングする(splatと併用不可)
	void mark(int first, int second, T value)
	{
		assert(!convert);
		assert(valid(first, second, false));
		buf[first + 1][second + 1] += value;
	}
	//区域内でマーキングした和を求める(markのみに使用)
	T sumquery(int firstcor, int secondcor, int firstlen, int secondlen)
	{
		assert(convert);
		int px = firstcor, py = secondcor;
		int qx = px + firstlen, qy = py + secondlen;
		assert(valid(px, py, false) && valid(qx, qy, true));
		return rawsum(px, py) + rawsum(qx, qy) - rawsum(px, qy) - rawsum(qx, py);
	}
	//範囲を塗りつぶす(markと併用不可)
	void splat(int firstcor, int secondcor, int firstlen, int secondlen, T value)
	{
		assert(!convert);
		int px = firstcor, py = secondcor;
		int qx = px + firstlen, qy = py + secondlen;
		assert(valid(px, py, false) && valid(qx, qy, true));
		buf[px][py] += value;
		buf[qx][qy] += value;
		buf[px][qy] -= value;
		buf[qx][py] -= value;
	}
	//あるマスの重なりを調べる(splatのみに使用)
	T depth(int first, int second)
	{
		assert(convert);
		assert(valid(first, second, false));
		return buf[first][second];
	}
	//累積する
	void imos()
	{
		convert = true;
		for (int i = 0; i < lim1; ++i)
		{
			for (int j = 0; j <= lim2; ++j)
			{
				buf[i + 1][j] += buf[i][j];
			}
		}
		for (int i = 0; i <= lim1; ++i)
		{
			for (int j = 0; j < lim2; ++j)
			{
				buf[i][j + 1] += buf[i][j];
			}
		}
	}
};

int imod(int a, int b) {
	return ((a % b) + b) % b;
}

int main(void)
{
	cin >> N >> K;
	imos2d<int>im(K * 3, K * 3);
	for (int i = 0; i < N; ++i) {
		int x, y;
		char c;
		cin >> x >> y >> c;
		bool co = (c == 'W');
		if (!co) {
			x += K;
		}
		x %= (K + K);
		y %= (K + K);
		x += (K + K);
		y += (K + K);
		x %= (K + K);
		y %= (K + K);
		im.splat(x, y, K, K, 1);
	}
	im.imos();
	int ans = 0;
	for (int x = 0; x < K; ++x) {
		for (int y = 0; y < K + K; ++y) {
			int dep = 0;
			for (int dx = -3; dx < 3; ++dx) {
				for (int dy = -3; dy < 3; ++dy) {
					int px = x + dx * K;
					int py = y + dy * K;
					if (px < 0 || py < 0 || px >= K * 3 || py >= K * 3)
						continue;
					if ((dx + dy) % 2 == 0)
						dep += im.depth(px, py);
				}
			}
			ans = max(dep, ans);
		}
	}
	cout << ans << endl;
	return 0;
}


Measured memory_bytes: 37632