#include <bits/stdc++.h>   using namespace std;   using ll = long long;   const int MOD = 1000000007;   int L;   ll sum[8040];   int len[8040];   int last[8040];   int lazy[8040];   void init(int v, int l, int r, const vector<int> &xs) {     len[v] = xs[r] - xs[l - 1];     if (l < r) {       int md = (l + r) >> 1;       init(v << 1, l, md, xs);       init(v << 1 | 1, md + 1, r, xs);     }   }   void reset(int v, int l, int r, const vector<int> &go) {     lazy[v] = -1;     if (l == r) {       sum[v] = ll(len[v]) * (L - go[l]);       last[v] = go[l];       return;     }     int md = (l + r) >> 1;     reset(v << 1, l, md, go);     reset(v << 1 | 1, md + 1, r, go);     sum[v] = sum[v << 1] + sum[v << 1 | 1];     last[v] = last[v << 1 | 1];   }   void push(int v, int l, int r) {     if (lazy[v] != -1) {       last[v] = lazy[v];       sum[v] = ll(len[v]) * (L - lazy[v]);       if (l < r) {         lazy[v << 1] = lazy[v];         lazy[v << 1 | 1] = lazy[v];       }       lazy[v] = -1;     }   }   void modify(int v, int l, int r, int L, int R, int qv) {     push(v, l, r);     if (L > r || R < l) return;     if (L <= l && r <= R) {       lazy[v] = qv;       push(v, l, r);       return;     }     int md = (l + r) >> 1;     modify(v << 1, l, md, L, R, qv);     modify(v << 1 | 1, md + 1, r, L, R, qv);     sum[v] = sum[v << 1] + sum[v << 1 | 1];     last[v] = last[v << 1 | 1];   }   int walk(int v, int l, int r, int qv) {     push(v, l, r);     if (last[v] <= qv) return -1;     if (l == r) return l;     int md = (l + r) >> 1;     int ans = walk(v << 1, l, md, qv);     if (ans == -1) ans = walk(v << 1 | 1, md + 1, r, qv);     return ans;   }   int main() {     ios_base::sync_with_stdio(false);     cin.tie(nullptr);     int N, K;     cin >> N >> K >> L;     vector<int> X(N), Y(N), C(N);     vector<int> xs = {-1, L};     vector<int> ys = {-1, L};     for (int i = 0; i < N; ++i) {       cin >> X[i] >> Y[i] >> C[i];       --C[i];       xs.emplace_back(X[i]);       ys.emplace_back(Y[i]);     }     sort(xs.begin(), xs.end());     xs.resize(unique(xs.begin(), xs.end()) - xs.begin());     sort(ys.begin(), ys.end());     ys.resize(unique(ys.begin(), ys.end()) - ys.begin());     int NX = xs.size();     int NY = ys.size();     {       vector<int> order(N);       iota(order.begin(), order.end(), 0);       sort(order.begin(), order.end(), [&](int i, int j) {         return make_pair(Y[i], -X[i]) > make_pair(Y[j], -X[j]);       });       vector<int> newX(N), newY(N), newC(N);       for (int i = 0; i < N; ++i) {         newX[i] = X[order[i]];         newY[i] = Y[order[i]];         newC[i] = C[order[i]];       }       X.swap(newX), Y.swap(newY), C.swap(newC);     }     init(1, 1, NX - 2, xs);     int ans = 0;     for (int yr = 1; yr + 1 < NY; ++yr) {       vector<vector<int>> addAt(NX);       for (int i = 0; i < N; ++i) {         if (Y[i] <= ys[yr]) {           int xi = lower_bound(xs.begin(), xs.end(), X[i]) - xs.begin();           addAt[xi].emplace_back(C[i]);         }       }       int bad = K;       vector<int> cnts(K);       auto inc = [&](int z) {         if (++cnts[z] == 1) --bad;       };       auto dec = [&](int z) {         if (--cnts[z] == 0) ++bad;       };       vector<int> go(NX);       int ptr = 0;       for (int i = 1; i + 1 < NX; ++i) {         while (bad && ptr + 2 < NX) {           ptr++;           for (int z : addAt[ptr]) inc(z);         }         if (bad)           go[i] = L;         else           go[i] = xs[ptr];         for (int z : addAt[i]) dec(z);       }       reset(1, 1, NX - 2, go);       vector<int> prv(N);       vector<int> nxt(N);       vector<map<int, int>> mp(K);       for (int i = 0; i < N; ++i) {         if (Y[i] <= ys[yr]) {           auto it = mp[C[i]].lower_bound(X[i]);           if (it == mp[C[i]].end()) {             nxt[i] = -1;           } else {             nxt[i] = it->second;           }           it = mp[C[i]].upper_bound(X[i]);           if (it == mp[C[i]].begin()) {             prv[i] = -1;           } else {             prv[i] = prev(it)->second;           }           mp[C[i]][X[i]] = i;         }       }       auto remove = [&](int i) {         int xprv = (prv[i] == -1 ? -1 : X[prv[i]]);         int xcur = X[i];         int xnxt = (nxt[i] == -1 ? L : X[nxt[i]]);         int l = lower_bound(xs.begin(), xs.end(), xprv) - xs.begin() + 1;         int r = walk(1, 1, NX - 2, xnxt);         if (r == -1) r = NX - 1;         --r;         r = min(r, int(lower_bound(xs.begin(), xs.end(), xcur) - xs.begin()));         if (l <= r) modify(1, 1, NX - 2, l, r, xnxt);       };       ptr = N - 1;       for (int yl = 1; yl <= yr; ++yl) {         ll add = sum[1] % MOD * (ys[yr + 1] - ys[yr]) % MOD *                  (ys[yl] - ys[yl - 1]) % MOD;         ans = (ans + add) % MOD;         while (ptr >= 0 && Y[ptr] == ys[yl]) remove(ptr--);       }       assert(sum[1] == 0);     }     cout << ans <<   n ;     return 0;   }