#include <bits/stdc++.h>   using namespace std;   long long read() {     long long a = 0;     char c = getchar();     while (c >  9  || c <  0 ) c = getchar();     while ( 0  <= c && c <=  9 ) {       a = a * 10 + c - 48;       c = getchar();     }     return a;   }   struct data {     long long x, y, c;     data(long long X = 0, long long Y = 0, long long C = 0) {       x = X;       y = Y;       c = C;     }   } w[2005], e[2005];   long long n, k, L;   bool cmp(data a, data b) { return a.x < b.x; };   bool cmp2(data a, data b) { return a.y < b.y; }   long long nxt[2005], f[2005];   multiset<long long> Set[2005];   long long sum[2005 << 2], Max[2005 << 2], tag[2005 << 2];   void pushup(long long x) {     sum[x] = (sum[(x << 1)] + sum[(x << 1 | 1)]) % 1000000007;     assert(Max[(x << 1)] <= Max[(x << 1 | 1)]);     Max[x] = Max[(x << 1 | 1)];   }   void build(long long x, long long l, long long r) {     tag[x] = 0;     if (l == r) {       sum[x] = f[l] * (e[l].y - e[l - 1].y) % 1000000007;       Max[x] = f[l];       return;     }     build((x << 1), l, ((l + r) >> 1));     build((x << 1 | 1), ((l + r) >> 1) + 1, r);     pushup(x);   }   void ptag(long long x, long long l, long long r, long long v) {     assert(Max[x] <= v);     sum[x] = v * (e[r].y - e[l - 1].y) % 1000000007;     tag[x] = Max[x] = v;   }   void pushdown(long long x, long long l, long long r) {     if (tag[x]) {       ptag((x << 1), l, ((l + r) >> 1), tag[x]);       ptag((x << 1 | 1), ((l + r) >> 1) + 1, r, tag[x]);       tag[x] = 0;     }   }   void chkmax(long long x, long long l, long long r, long long b, long long e,               long long v) {     if (r < b || l > e) return;     if (l == r && Max[x] > v) return;     if (Max[x] <= v && b <= l && r <= e) {       ptag(x, l, r, v);       return;     }     bool flag = (v > Max[(x << 1)]);     pushdown(x, l, r);     chkmax((x << 1), l, ((l + r) >> 1), b, e, v);     if (flag) chkmax((x << 1 | 1), ((l + r) >> 1) + 1, r, b, e, v);     pushup(x);   }   signed main() {     n = read();     k = read();     L = read();     for (long long i = 1; i <= n; ++i) {       w[i].x = read() + 1;       w[i].y = read() + 1;       w[i].c = read();       e[i] = w[i];     }     sort(w + 1, w + 1 + n, cmp);     sort(e + 1, e + 1 + n, cmp2);     e[n + 1].y = L + 1;     w[n + 1].x = w[n + 2].x = L + 1;     w[n + 1].y = L + 1;     long long ans = 0;     for (long long i = n; i; --i) {       long long tmp = (w[i].x - w[i - 1].x);       if (!tmp) continue;       multiset<long long> S;       S.clear();       for (long long i = 1; i <= k; ++i) {         S.insert(L + 1), nxt[i] = L + 1;         Set[i].clear();         Set[i].insert(L + 1);         Set[i].insert(0);       }       for (long long j = n; j; --j) {         if (e[j].x >= w[i].x) {           S.erase(S.find(nxt[e[j].c]));           nxt[e[j].c] = e[j].y;           S.insert(nxt[e[j].c]);           Set[e[j].c].insert(e[j].y);         }         f[j] = (*(--S.end()));       }       build(1, 1, n);       for (long long j = n + 1; j > i; --j) {         if (w[j].c) {           assert(Set[w[j].c].find(w[j].y) != Set[w[j].c].end());           Set[w[j].c].erase(Set[w[j].c].find(w[j].y));           multiset<long long>::iterator it = --Set[w[j].c].upper_bound(w[j].y),                                         ir = it;           ++ir;           long long ll = lower_bound(e, e + 1 + n, data(0, *it, 0), cmp2) - e;           if (ll) assert(e[ll].y != e[ll - 1].y);           chkmax(1, 1, n, ll + 1, n, *ir);         }         long long res = ((L + 1) * e[n].y - sum[1] + 1000000007) % 1000000007;         ans =             (ans + (res * tmp % 1000000007 * (w[j].x - w[j - 1].x))) % 1000000007;       }     }     printf( %lld n , ans);     return 0;   }