/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author JustLive
 */

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define forr(i, a, b) for (int i = (int)(a); i >= (int)(b); --i)
#define rep(i, a, b, s) for (int i = (int)(a); i <= (int)(b); i += s)
#define repr(i, a, b, s) for (int i = (int)(a); i >= (int)(b); i -= s)

#ifdef LOCAL_SYSTEM
#define DEBUG(x) cerr << #x << ": " << (x) << endl;
#define DEBUGARR(a, n) cerr << #a << ": "; print_array(cerr, a, n); cerr << endl;
#else
#define DEBUG(x)
#define DEBUGARR(a, n)
#endif

using namespace std;

template<typename T> void print_sequential_container(ostream& stream, const vector<T>& c) {
    stream << "[";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "]";
}

template<typename T> void print_array(ostream& stream, T a[], int n) {
    stream << "[";
    for (int i = 0; i < n; i++) {
        stream << a[i];
        if (i != n - 1) {
            stream << ", ";
        }
    }
    stream << "]";
}

template<typename T> void print_set(ostream& stream, const T& c) {
    stream << "{";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "}";
}

template<typename T> void print_map(ostream& stream, const T& c) {
    stream << "{";
    auto &last = *(--c.end());
    for (auto &e: c) {
        stream << e.fi << ": " << e.se;
        if (e != last) {
            stream << ", ";
        }
    }
    stream << "}";
}

template<typename T> ostream& operator << (ostream& stream, const vector<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const list<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const forward_list<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T, size_t N> ostream& operator << (ostream& stream, const array<T, N>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const deque<T>& c) {
    print_sequential_container(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const stack<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.top());
        c.pop();
    }
    for (int i = ((int)v.size()) - 1; i >= 0; i--) {
        c.push(v[i]);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const queue<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.front());
        c.pop();
    }
    for (T e: v) {
        c.push(e);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const priority_queue<T>& c) {
    vector<T> v;
    while (not c.empty()) {
        v.pb(c.top());
        c.pop();
    }
    for (T e: v) {
        c.push(e);
    }
    print_sequential_container(stream, v);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const set<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const unordered_set<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const multiset<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T> ostream& operator << (ostream& stream, const unordered_multiset<T>& c) {
    print_set(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const map<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const unordered_map<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const multimap<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const unordered_multimap<T1, T2>& c) {
    print_map(stream, c);
    return stream;
}

template<typename T1, typename T2> ostream& operator << (ostream& stream, const pair<T1, T2>& p) {
    stream << "(" << p.fi << ", " << p.se << ")";
    return stream;
}

template<typename T>
size_t make_hash(const T& v) {
    return std::hash<T>()(v);
}

size_t hash_combine(const size_t& h, const size_t& v) {
    return h ^ (v + 0x9e3779b9 + (h << 6) + (h >> 2));
}

namespace std {
    template <typename T1, typename T2>
    struct hash<pair<T1, T2>> {
    public:
        size_t operator()(const pair<T1, T2>& p) const {
            return hash_combine(make_hash(p.fi), make_hash(p.se));
        }
    };
};

template<typename T>
struct hash_container
{
    size_t operator()(const T& c) const {
        size_t h = 0;
        for(const auto& e: c) {
            h = hash_combine(h, make_hash(e));
        }
        return h;
    }
};

typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef vector<vi> vvi;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef pair<ll, ll> pll;
typedef double ld;

template<typename T> bool amin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<typename T> bool amax(T &a, T b) { return a < b ? (a = b, true) : false; }

const int mod = 1000000007;
const int inf = 1000000000;
const ll infll = (ll)inf * (ll)inf;
const int maxn = 100000;

vector<vector<int>> dp;

int k;

int g(int i, int j) {
    if (max(i, j) >= 2*k or min(i, j) + k - 1 < 0) {
        return 0;
    }
    int ii = min(2*k-1,i+k-1);
    int jj = min(2*k-1,j+k-1);
    int t = i > 0 ? dp[i-1][jj] : 0;
    int l = j > 0 ? dp[ii][j-1] : 0;
    int tl = i > 0 and j > 0 ? dp[i-1][j-1] : 0;
    return dp[ii][jj] - t - l + tl;
}

class TaskB {
public:
    void solve(istream& in, ostream& out) {
        dp.clear();
        int n;
        in >> n >> k;
        vector<pii> v(n);
        dp.resize(2 * k, vector<int>(2 * k, 0));
        forn(i, n) {
            int x, y;
            char c;
            in >> x >> y >> c;
            if (c == 'W') {
                y += k;
            }
            x %= 2 * k;
            y %= 2 * k;
            dp[x][y]++;
        }
        forn(i, 2*k) {
            forn(j, 2*k) {
                int t = i > 0 ? dp[i-1][j] : 0;
                int l = j > 0 ? dp[i][j-1] : 0;
                int tl = i > 0 and j > 0 ? dp[i-1][j-1] : 0;
                dp[i][j] += t + l - tl;
            }
        }
        int res = 0;
        forn(i, 2*k) {
            forn(j, 2*k) {
                int c = 0;
                fore(d, -2, 2) {
                    fore(e, -2, 2) {
                        if ((d + e) % 2 == 0) {
                            int p = g(i + d * k, j + e * k);
                            c += p;
                        }
                    }
                }
                amax(res, c);
            }
        }
        out << res;
    }
};


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    TaskB solver;
    std::istream& in(std::cin);
    std::ostream& out(std::cout);
    solver.solve(in, out);
    return 0;
}


Measured memory_bytes: 16768