// -YDK- {{{
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <numeric>
#include <string>
#include <cstdio>
#include <vector>
#include <tuple>
#include <cmath>
#include <queue>
#include <regex>
#include <set>
#include <map>
using namespace std;
#define eb emplace_back
#define emp emplace
#define fi first
#define se second
#define debug(...) fprintf(stderr, __VA_ARGS__ )
#define outl(x) cout << (x) << '\n'
#define outl2(x,y) cout << (x) << ' ' << (y) << '\n'
#define endl '\n'
#define rep(i,n) for(int i=0; i<(int)(n); ++i)
#define ALL(x) x.begin(), x.end()
#define YES(f,y,n) cout << ((f)? (#y):(#n)) << '\n'
#define ODD(n) ((n)&1)
#define EVEN(n) (!ODD(n))
template<class A, class B>inline bool chmax(A &a, B b){return b>a ? a=b,1 : 0;}
template<class A, class B>inline bool chmin(A &a, B b){return b<a ? a=b,1 : 0;}
template<class T>using MaxHeap = priority_queue< T, vector<T>, greater<T> >;
using ll = long long;
using pii = pair<int, int>;
using byte= unsigned char;
inline bool inside(int x, int y, int W, int H) { return x>=0 && y>=0 && x<W && y<H; }
constexpr int INF = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int dx[] = {1, 0, -1, 0};
constexpr int dy[] = {0, 1, 0, -1};
struct Point: public pii {
    int &x = this->first,   &y = this->second;
    Point(int x, int y): pii(x, y) {}
};
// }}}
constexpr int LIM = (int)2e5 + 5;

#define int long long

struct Star
{
    int x, y, f;
    explicit Star(int x, int y, int f): x(x), y(y), f(f) {}
    explicit Star(): x(0), y(0), f(0) {}

    bool operator < (const Star &s)const { return f < s.f; }
    bool operator > (const Star &s)const { return f > s.f; }
};

struct SegTree
{
    using Monoid = int(*)(int, int);

    vector<int> dat;
    int size;
    const int SENTINEL; // 番兵, デフォルト値
    Monoid f;

    explicit SegTree(int n, int sntinel, const Monoid &monoid)
        : SENTINEL(sntinel), f(monoid)
    {
        for(size=1; size<n; size*=2);
        dat.assign(size*2 + 5, SENTINEL);
    }

    void update(int i, int v)
    {
        dat[i+=size-1] = v;
        while (i > 0)  {
            i = (i-1) / 2;
            dat[i] = f(dat[i*2+1], dat[i*2+2]);
        }
    }

    int query(int a, int b, int k, int l, int r)
    {
        if (r <= a || b <= l) return SENTINEL;
        if (a <= l && r <= b) return dat[k];
        int mid = (l + r) / 2;
        return f( query(a,b, 2*k+1, l, mid), query(a,b, 2*k+2, mid, r) );
    }

    int query(int a, int b) { return query(a,b, 0, 0, size); }

};

int N, d;
Star star[LIM];

signed main(void)
{
#ifndef DEBUG
    cin.tie(nullptr), ios::sync_with_stdio(false);
#endif

    cin >> N >> d;
    rep(i, N) {
        int x, y, f;
        cin >> x >> y >> f;
        star[i] = Star(x, y, f);
    }

    sort(star, star+N);

    SegTree minX(N, INF, [](int a, int b){return min(a,b);});
    SegTree minY(N, INF, [](int a, int b){return min(a,b);});

    SegTree maxX(N, 0, [](int a, int b){return max(a,b);});
    SegTree maxY(N, 0, [](int a, int b){return max(a,b);});

    rep(i, N) {
        minX.update(i, star[i].x);
        maxX.update(i, star[i].x);

        minY.update(i, star[i].y);
        maxY.update(i, star[i].y);
    }

#ifdef DEBUG
    rep(i, N) {
        printf("%d  (%2d, %2d)\n", star[i].f, star[i].x, star[i].y);
    }
#endif

    ll ans = 0;

    rep(i, N-1) {
        int k = upper_bound(star, star+N, Star(0,0,star[i].f + d)) - star;

        ll sx = minX.query(i, k);
        ll sy = minY.query(i, k);
        ll tx = maxX.query(i, k);
        ll ty = maxY.query(i, k);

        chmax(ans, (tx-sx) * (ty - sy));
    }

    outl(ans);

    return 0;
}




Measured memory_bytes: 23892