### BUGGY CODE ###

import math
class SegmentTree:
    def __init__(self, dat, f, sentinel):
        self.pad = 2 ** math.ceil(math.log(len(dat),2))
        self.dat = [None] * self.pad + dat + [sentinel] * (self.pad - len(dat))
        self.f = f
        self.sentinel = sentinel
        for i in range(self.pad - 1, 0, -1):
            self.dat[i] = self.f(self.dat[i * 2:i * 2 + 2])
        
    def q(self,l,r):
        return self.f(self.dat[i] for i in self.get_index(l,r))
    #[l,r)
    def get_index(self,l,r):
        l += self.pad 
        r += self.pad
        while l < r:
            if r & 1:
                r -= 1
                yield r
            if l & 1:
                yield l
                l += 1
            l >>= 1
            r >>= 1
    def q2(self,index):
        return self.f(self.dat[i] for i in index)

    def get_index2(self,l,r):
        l += self.pad 
        r += self.pad
        ret = []
        while l < r:
            if r & 1:
                r -= 1
                ret.append(r)
            if l & 1:
                ret.append(l)
                l += 1
            l >>= 1
            r >>= 1
        return ret
import sys
f = sys.stdin

_, d = map(int, f.readline().split())

x,y = {},{}
for line in f:
    xi, yi, bi = map(int, line.split())
    if bi not in x:
        x[bi],y[bi] = [],[]
    x[bi].append(xi)
    y[bi].append(yi)

b = sorted(x.keys())

xmax = SegmentTree([max(x[bi]) for bi in b],max,sentinel = -1)
xmin = SegmentTree([min(x[bi]) for bi in b],min,sentinel = 2000001)
ymax = SegmentTree([max(y[bi]) for bi in b],max,sentinel = -1)
ymin = SegmentTree([min(y[bi]) for bi in b],min,sentinel = 2000001)

def get_lr(b,d):
    l = r = 0
    while r < len(b):
        while b[l] + d < b[r]:
            l += 1
        for r in range(r,len(b)):
            if b[l] + d < b[r]:
                r -= 1
                break
        r += 1
        yield l,r
        l += 1
    
#max_size = max((xmax.q(l,r) - xmin.q(l,r)) * (ymax.q(l,r) - ymin.q(l,r)) for l,r in get_lr(b,d))
size = []
for l,r in get_lr(b,d):
    index = xmax.get_index2(l,r)
    size.append((xmax.q2(index) - xmin.q2(index)) * (ymax.q2(index) - ymin.q2(index)))
print(max(size))

### FIXED CODE ###

import math
def segmentTree(dat, f, sentinel):
        pad = 2 ** math.ceil(math.log(len(dat),2))
        dat = [0] * pad + dat + [sentinel] * (pad - len(dat))
        for i in range(pad - 1, 0, -1):
            dat[i] = f(dat[i * 2],dat[i * 2 + 1])
        return dat

def get_lr(b,d):
    l = r = 0
    while r < len(b):
        while b[l] + d < b[r]:
            l += 1
        for r in range(r,len(b)):
            if b[l] + d < b[r]:
                r -= 1
                break
        r += 1
        yield l,r
        l += 1
    
import sys
f = sys.stdin

_, d = map(int, f.readline().split())

xyb = []
for line in f:
    xyb.append(tuple(map(int, line.split())))
from operator import itemgetter
xyb.sort(key=itemgetter(2))

x = [xybi[0] for xybi in xyb]
y = [xybi[1] for xybi in xyb]
b = [xybi[2] for xybi in xyb]

xmax = segmentTree(x,max,sentinel = 0)
xmin = segmentTree(x,min,sentinel = 2000000)
ymax = segmentTree(y,max,sentinel = 0)
ymin = segmentTree(y,min,sentinel = 2000000)


pad = len(xmax) // 2
max_size = 0
def create_index(l,r):
    index = []
    ia = index.append
    while l < r:
        if r & 1:
            r -= 1
            ia(r)
        if l & 1:
            ia(l)
            l += 1
        l >>= 1
        r >>= 1
    return index

for l,r in get_lr(b,d):
    l += pad 
    r += pad
    index = create_index(l,r)

    now_xmax = max(xmax[i] for i in index)
    now_ymax = max(ymax[i] for i in index)
    if max_size < now_xmax * now_ymax:
        max_size = max(max_size,((now_xmax - min(xmin[i] for i in index)) * (now_ymax - min(ymin[i] for i in index))))
print(max_size)