#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt"


#define Seg_Max_N (1<<18) 

using Value = pair<long long int,long long int>;
const Value ini = (make_pair(1e18, 0));
struct segtree {
	int N;
	vector<int>nums;
	vector<Value>dat;

	segtree() {}
	segtree(int n) :dat(2 * Seg_Max_N) ,nums(2*Seg_Max_N) {
		N = 1;
		while (N < n) N *= 2;
		for (int i = 0; i < 2 * N - 1; i++) {
			dat[i] = ini;
		}
	}
	// update k th element
	void update(int k, Value a) {
		k += N - 1; // leaf
		if (a == ini) {
			nums[k]--;
			if (!nums[k])dat[k] = a;
		}
		else {
			nums[k]++;
			dat[k] = a;
		}
		while (k > 0) {
			k = (k - 1) / 2;
			const Value al(dat[k * 2 + 1]);
			const Value ar(dat[k * 2 + 2]);
			dat[k] = make_pair(min(al.first,ar.first), max(al.second,ar.second));
		}
	}
	// min [a, b)
	Value  query(int a, int b) { return query(a, b, 0, 0, N); }
	Value  query(int a, int b, int k, int l, int r) {
		if (r <= a or b <= l) return ini;
		if (a <= l and r <= b) return dat[k];
		const int m = (l + r) / 2;
		const Value al(query(a, b, k * 2 + 1, l, m));
		const Value ar(query(a, b, k * 2 + 2, m, r));
		return make_pair(min(al.first, ar.first), max(al.second, ar.second));
	}
};
struct star{
	int x;
	int y;
	int light;
};
const int amax = 200001;
struct Compress {
	map<int, int>mp;
	map<int, int>revmp;

	Compress(vector<int>vs) {
		sort(vs.begin(), vs.end());
		int aend=unique(vs.begin(), vs.end())-vs.begin();
		for (int i = 0; i < aend; ++i) {
			mp[vs[i]] = i;
			revmp[i] = vs[i];
		}
	}
	Compress(const set<int>&vs) {
		int num = 0;
		for (auto v : vs) {
			mp[v] = num;
			revmp[num] = v;
			num++;
		}
	}
};
int main() {
	int N, D; cin >> N >> D;
	vector<int>xs, ys;
	segtree segx(amax), segy(amax);
	vector<star>stars;
	for (int i = 0; i < N; ++i) {
		int x, y, b; cin >> x >> y >> b;
		stars.push_back(star{ x,y,b });
		xs.push_back(x);
		ys.push_back(y);
	}
	Compress cpx(xs), cpy(ys);
	sort(stars.begin(), stars.end(), [](const star&l, const star&r) {
		return l.light < r.light;
	});
	for (auto &sta : stars) {
		sta.x = cpx.mp[sta.x];
		sta.y = cpy.mp[sta.y];
	}
	int l = 0;
	int r = 0;
	long long int ans = 0;
	{
		segx.update(stars[0].x, make_pair(stars[0].x, stars[0].x));
		segy.update(stars[0].y, make_pair(stars[0].y, stars[0].y));
		auto px(segx.query(0, amax));
		auto py(segy.query(0, amax));
		ans = max(ans, (px.second - px.first)*(py.second - py.first));
	}
	while (r<N-1) {
		if (stars[r+1].light <= stars[l].light+D) {
			r++;
			segx.update(stars[r].x, make_pair(stars[r].x, stars[r].x));
			segy.update(stars[r].y, make_pair(stars[r].y, stars[r].y));
			auto px(segx.query(0, amax));
			auto py(segy.query(0, amax));
			long long int disx = cpx.revmp[px.second] - cpx.revmp[px.first];
			long long int disy = cpy.revmp[py.second] - cpy.revmp[py.first];
			ans = max(ans, disx*disy);
		}
		else {
			if (l != r) {
				segx.update(stars[l].x, ini);
				segy.update(stars[l].y,ini);
				l++;
			}
			else {
				r++;
				segx.update(stars[r].x, make_pair(stars[r].x, stars[r].x));
				segy.update(stars[r].y, make_pair(stars[r].y, stars[r].y));
				segx.update(stars[l].x, ini);
				segy.update(stars[l].y, ini);
				l++;
				auto px(segx.query(0, amax));
				auto py(segy.query(0, amax));
				ans = max(ans, (px.second - px.first)*(py.second - py.first));
			}
		}
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 63888