You are given n segments on a number line, numbered from 1 to n. The i-th segments covers all integer points from l_i to r_i and has a value w_i.

You are asked to select a subset of these segments (possibly, all of them). Once the subset is selected, it's possible to travel between two integer points if there exists a selected segment that covers both of them. A subset is good if it's possible to reach point m starting from point 1 in arbitrary number of moves.

The cost of the subset is the difference between the maximum and the minimum values of segments in it. Find the minimum cost of a good subset.

In every test there exists at least one good subset.

Input

The first line contains two integers n and m (1 ≤ n ≤ 3 ⋅ 10^5; 2 ≤ m ≤ 10^6) — the number of segments and the number of integer points.

Each of the next n lines contains three integers l_i, r_i and w_i (1 ≤ l_i < r_i ≤ m; 1 ≤ w_i ≤ 10^6) — the description of the i-th segment.

In every test there exists at least one good subset.

Output

Print a single integer — the minimum cost of a good subset.

Examples

Input


5 12
1 5 5
3 4 10
4 10 6
11 12 5
10 12 3


Output


3


Input


1 10
1 10 23


Output


0

Source: codeforces | Difficulty: HARD
Tags: Tree algorithms

Data structures

Sorting

Amortized analysis


Solutions:
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

class segment_tree(object):

	def merge(self, num, minimum):
		return min(minimum, num)

	def __init__(self, n, initial):
		self.n = n + 1
		self.arr = [0] * (2 * n + 2)
		self.lazy = [0] * (n + 1)
		self.layer = n.bit_length() + 1
		for i in range(2 * n, n, -1):
			self.arr[i] = initial[i - n - 1]
		for i in range(n - 1, -1, -1):
			self.arr[i] = self.merge(self.arr[2 * i], self.arr[2 * i + 1])

	def rebuild(self, index):
		index = index >> 1
		while index > 0:
			self.arr[index] = self.merge(self.arr[index << 1], self.arr[index << 1 | 1]) + self.lazy[index]
			index = index >> 1

	def addtarget(self, index, target):
		self.arr[index] += target
		if index < self.n:
			self.lazy[index] += target

	def update(self, left, right, target):
		(i, j) = (self.n + left, self.n + right + 1)
		(i0, j0) = (i, j)
		while i < j:
			if i & 1:
				self.addtarget(i, target)
				i += 1
			if j & 1:
				j -= 1
				self.addtarget(j, target)
			i = i >> 1
			j = j >> 1
		self.rebuild(i0)
		self.rebuild(j0)

	def pushdown(self, index):
		for move in range(self.layer, 0, -1):
			father = index >> move
			if father < 1 or father >= self.n:
				continue
			if self.lazy[father] == 0:
				continue
			child = father << 1
			self.arr[child] += self.lazy[father]
			self.arr[child + 1] += self.lazy[father]
			if child < self.n:
				self.lazy[child] += self.lazy[father]
			if child + 1 < self.n:
				self.lazy[child + 1] += self.lazy[father]
			self.lazy[father] = 0

	def query(self, left, right):
		(i, j) = (self.n + left, self.n + right + 1)
		output = 2147483647
		self.pushdown(i)
		self.pushdown(j)
		while i < j:
			if i & 1:
				output = self.merge(self.arr[i], output)
				i += 1
			if j & 1:
				j -= 1
				output = self.merge(self.arr[j], output)
			i = i >> 1
			j = j >> 1
		return output

def main(t):
	(n, m) = map(int, input().split())
	segments = []
	for _ in range(n):
		(front, rear, w) = map(int, input().split())
		segments.append([w, front - 1, rear - 1])
	segments = sorted(segments)
	over = segment_tree(m - 1, [0] * (m - 1))
	front = 0
	ans = 2147483647
	flag = False
	for i in range(n):
		over.update(segments[i][1], segments[i][2] - 1, 1)
		if not flag and over.query(0, m - 2) > 0:
			flag = True
		if flag:
			while over.query(segments[front][1], segments[front][2] - 1) > 1:
				front += 1
				over.update(segments[front - 1][1], segments[front - 1][2] - 1, -1)
			ans = min(ans, segments[i][0] - segments[front][0])
	print(ans)
T = 1
t = 1
while t <= T:
	main(t)
	t += 1


def naiveSolve():
	return

def solve():
	return

class LazySegmentTree:

	def __init__(self, n, default=0, func=max):
		self._default = default
		self._func = func
		self._len = n
		self._size = _size = 1 << (self._len - 1).bit_length()
		self._lazy = [0] * (2 * _size)
		self.data = [0] * (2 * _size)

	def __len__(self):
		return self._len

	def _push(self, idx):
		(q, self._lazy[idx]) = (self._lazy[idx], 0)
		self._lazy[2 * idx] += q
		self._lazy[2 * idx + 1] += q
		self.data[2 * idx] += q
		self.data[2 * idx + 1] += q

	def _update(self, idx):
		for i in reversed(range(1, idx.bit_length())):
			self._push(idx >> i)

	def _build(self, idx):
		idx >>= 1
		while idx:
			self.data[idx] = min(self.data[2 * idx], self.data[2 * idx + 1]) + self._lazy[idx]
			idx >>= 1

	def add(self, start, stop, value):
		stop += 1
		start = start_copy = start + self._size
		stop = stop_copy = stop + self._size
		while start < stop:
			if start & 1:
				self._lazy[start] += value
				self.data[start] += value
				start += 1
			if stop & 1:
				stop -= 1
				self._lazy[stop] += value
				self.data[stop] += value
			start >>= 1
			stop >>= 1
		self._build(start_copy)
		self._build(stop_copy - 1)

	def query(self, start, stop, default=0):
		stop += 1
		start += self._size
		stop += self._size
		self._update(start)
		self._update(stop - 1)
		res = default
		while start < stop:
			if start & 1:
				res = min(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = min(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'LazySegmentTree({0})'.format(self.data)

def main():
	(n, m) = readIntArr()
	wlr = []
	for _ in range(n):
		(l, r, w) = readIntArr()
		r -= 1
		wlr.append((w, l, r))
	wlr.sort()
	lst = LazySegmentTree(m + 1, default=inf, func=min)
	ans = inf
	left = 0
	for right in range(n):
		lst.add(wlr[right][1], wlr[right][2], 1)
		while lst.query(1, m - 1, default=inf) >= 1:
			ans = min(ans, wlr[right][0] - wlr[left][0])
			lst.add(wlr[left][1], wlr[left][2], -1)
			left += 1
	print(ans)
	return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(x):
	print('{}'.format(x))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(ans))
	sys.stdout.flush()
inf = float('inf')
MOD = 998244353
from math import gcd, floor, ceil
for _abc in range(1):
	main()


import sys
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
from operator import itemgetter
(n, m) = map(int, input().split())
A = [tuple(map(int, input().split())) for i in range(n)]
A.sort(key=itemgetter(2))
seg_el = 1 << (m + 5).bit_length()
SEG = [0] * (2 * seg_el)
LAZY = [0] * (2 * seg_el)

def indexes(L, R):
	INDLIST = []
	R -= 1
	L >>= 1
	R >>= 1
	while L != R:
		if L > R:
			INDLIST.append(L)
			L >>= 1
		else:
			INDLIST.append(R)
			R >>= 1
	while L != 0:
		INDLIST.append(L)
		L >>= 1
	return INDLIST

def adds(l, r, x):
	L = l + seg_el
	R = r + seg_el
	L //= L & -L
	R //= R & -R
	UPIND = indexes(L, R)
	for ind in UPIND[::-1]:
		if LAZY[ind] != 0:
			plus_lazy = LAZY[ind]
			SEG[ind << 1] += plus_lazy
			SEG[1 + (ind << 1)] += plus_lazy
			LAZY[ind << 1] += plus_lazy
			LAZY[1 + (ind << 1)] += plus_lazy
			LAZY[ind] = 0
	while L != R:
		if L > R:
			SEG[L] += x
			LAZY[L] += x
			L += 1
			L //= L & -L
		else:
			R -= 1
			SEG[R] += x
			LAZY[R] += x
			R //= R & -R
	for ind in UPIND:
		SEG[ind] = min(SEG[ind << 1], SEG[1 + (ind << 1)])

def getvalues(l, r):
	L = l + seg_el
	R = r + seg_el
	L //= L & -L
	R //= R & -R
	UPIND = indexes(L, R)
	for ind in UPIND[::-1]:
		if LAZY[ind] != 0:
			plus_lazy = LAZY[ind]
			SEG[ind << 1] += plus_lazy
			SEG[1 + (ind << 1)] += plus_lazy
			LAZY[ind << 1] += plus_lazy
			LAZY[1 + (ind << 1)] += plus_lazy
			LAZY[ind] = 0
	ANS = 1 << 28
	while L != R:
		if L > R:
			ANS = min(ANS, SEG[L])
			L += 1
			L //= L & -L
		else:
			R -= 1
			ANS = min(ANS, SEG[R])
			R //= R & -R
	return ANS
ind = 0
ANS = 1 << 28
for i in range(n):
	while ind < n and getvalues(1, m) == 0:
		(x, y, z) = A[ind]
		adds(x, y, 1)
		ind += 1
	if getvalues(1, m) != 0:
		ANS = min(ANS, A[ind - 1][2] - A[i][2])
	(x, y, z) = A[i]
	adds(x, y, -1)
print(ANS)


def naiveSolve():
	return

def solve():
	return

class Lazysegtree:

	def __init__(self, A, defaultVal, initialize=True, segf=min):
		intv = defaultVal
		self.N = len(A)
		self.N0 = 2 ** (self.N - 1).bit_length()
		self.intv = intv
		self.segf = segf
		self.lazy = [0] * (2 * self.N0)
		if initialize:
			self.data = [intv] * self.N0 + A + [intv] * (self.N0 - self.N)
			for i in range(self.N0 - 1, 0, -1):
				self.data[i] = self.segf(self.data[2 * i], self.data[2 * i + 1])
		else:
			self.data = [intv] * (2 * self.N0)

	def _ascend(self, k):
		k = k >> 1
		c = k.bit_length()
		for j in range(c):
			idx = k >> j
			self.data[idx] = self.segf(self.data[2 * idx], self.data[2 * idx + 1]) + self.lazy[idx]

	def _descend(self, k):
		k = k >> 1
		idx = 1
		c = k.bit_length()
		for j in range(1, c + 1):
			idx = k >> c - j
			ax = self.lazy[idx]
			if not ax:
				continue
			self.lazy[idx] = 0
			self.data[2 * idx] += ax
			self.data[2 * idx + 1] += ax
			self.lazy[2 * idx] += ax
			self.lazy[2 * idx + 1] += ax

	def query(self, l, r):
		r += 1
		L = l + self.N0
		R = r + self.N0
		Li = L // (L & -L)
		Ri = R // (R & -R)
		self._descend(Li)
		self._descend(Ri - 1)
		s = self.intv
		while L < R:
			if R & 1:
				R -= 1
				s = self.segf(s, self.data[R])
			if L & 1:
				s = self.segf(s, self.data[L])
				L += 1
			L >>= 1
			R >>= 1
		return s

	def add(self, l, r, x):
		r += 1
		L = l + self.N0
		R = r + self.N0
		Li = L // (L & -L)
		Ri = R // (R & -R)
		while L < R:
			if R & 1:
				R -= 1
				self.data[R] += x
				self.lazy[R] += x
			if L & 1:
				self.data[L] += x
				self.lazy[L] += x
				L += 1
			L >>= 1
			R >>= 1
		self._ascend(Li)
		self._ascend(Ri - 1)

	def binsearch(self, l, r, check, reverse=False):
		r += 1
		L = l + self.N0
		R = r + self.N0
		Li = L // (L & -L)
		Ri = R // (R & -R)
		self._descend(Li)
		self._descend(Ri - 1)
		(SL, SR) = ([], [])
		while L < R:
			if R & 1:
				R -= 1
				SR.append(R)
			if L & 1:
				SL.append(L)
				L += 1
			L >>= 1
			R >>= 1
		if reverse:
			for idx in SR + SL[::-1]:
				if check(self.data[idx]):
					break
			else:
				return -1
			while idx < self.N0:
				ax = self.lazy[idx]
				self.lazy[idx] = 0
				self.data[2 * idx] += ax
				self.data[2 * idx + 1] += ax
				self.lazy[2 * idx] += ax
				self.lazy[2 * idx + 1] += ax
				idx = idx << 1
				if check(self.data[idx + 1]):
					idx += 1
			return idx - self.N0
		else:
			for idx in SL + SR[::-1]:
				if check(self.data[idx]):
					break
			else:
				return -1
			while idx < self.N0:
				ax = self.lazy[idx]
				self.lazy[idx] = 0
				self.data[2 * idx] += ax
				self.data[2 * idx + 1] += ax
				self.lazy[2 * idx] += ax
				self.lazy[2 * idx + 1] += ax
				idx = idx << 1
				if not check(self.data[idx]):
					idx += 1
			return idx - self.N0

def main():
	(n, m) = readIntArr()
	wlr = []
	for _ in range(n):
		(l, r, w) = readIntArr()
		r -= 1
		wlr.append((w, l, r))
	wlr.sort()
	arr = [0] * (m + 1)
	lst = Lazysegtree(arr, inf, initialize=True, segf=min)
	ans = inf
	left = 0
	for right in range(n):
		lst.add(wlr[right][1], wlr[right][2], 1)
		while lst.query(1, m - 1) >= 1:
			ans = min(ans, wlr[right][0] - wlr[left][0])
			lst.add(wlr[left][1], wlr[left][2], -1)
			left += 1
	print(ans)
	return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(x):
	print('{}'.format(x))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(ans))
	sys.stdout.flush()
inf = float('inf')
MOD = 998244353
from math import gcd, floor, ceil
for _abc in range(1):
	main()


import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

class LazySegmentTree:

	def __init__(self, data, default=0, func=min):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self._lazy = [0] * (2 * _size)
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __len__(self):
		return self._len

	def _push(self, idx):
		(q, self._lazy[idx]) = (self._lazy[idx], 0)
		self._lazy[2 * idx] += q
		self._lazy[2 * idx + 1] += q
		self.data[2 * idx] += q
		self.data[2 * idx + 1] += q

	def _update(self, idx):
		for i in reversed(range(1, idx.bit_length())):
			self._push(idx >> i)

	def _build(self, idx):
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1]) + self._lazy[idx]
			idx >>= 1

	def add(self, start, stop, value):
		start = start_copy = start + self._size
		stop = stop_copy = stop + self._size
		while start < stop:
			if start & 1:
				self._lazy[start] += value
				self.data[start] += value
				start += 1
			if stop & 1:
				stop -= 1
				self._lazy[stop] += value
				self.data[stop] += value
			start >>= 1
			stop >>= 1
		self._build(start_copy)
		self._build(stop_copy - 1)

	def query(self, start, stop, default=1000000000.0):
		start += self._size
		stop += self._size
		self._update(start)
		self._update(stop - 1)
		res = default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'LazySegmentTree({0})'.format(self.data)
(n, m) = [int(i) for i in input().split()]
a = []
b = []
for i in range(n):
	curr = [int(i) for i in input().split()]
	a.append(curr[:])
	b.append([curr[2], curr[0] - 1, curr[1] - 1])
b.sort()
start = 0
end = 0
cnt = [0] * m
st = LazySegmentTree(cnt)
ans = 1000000000.0
while start < n:
	while st.query(0, m - 1):
		ans = min(ans, b[end - 1][0] - b[start][0])
		st.add(b[start][1], b[start][2], -1)
		start += 1
	if end == n:
		break
	while end < n and st.query(0, m - 1) == 0:
		st.add(b[end][1], b[end][2], 1)
		end += 1
print(ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
from math import inf, log2

class LazySegmentTree:

	def __init__(self, array, func=max):
		self.n = len(array)
		self.size = 2 ** (int(log2(self.n - 1)) + 1) if self.n != 1 else 1
		self.func = func
		self.default = 0 if self.func != min else inf
		self.data = [self.default] * (2 * self.size)
		self.lazy = [0] * (2 * self.size)
		self.process(array)

	def process(self, array):
		self.data[self.size:self.size + self.n] = array
		for i in range(self.size - 1, -1, -1):
			self.data[i] = self.func(self.data[2 * i], self.data[2 * i + 1])

	def push(self, index):
		self.lazy[2 * index] += self.lazy[index]
		self.lazy[2 * index + 1] += self.lazy[index]
		self.data[2 * index] += self.lazy[index]
		self.data[2 * index + 1] += self.lazy[index]
		self.lazy[index] = 0

	def build(self, index):
		index >>= 1
		while index:
			self.data[index] = self.func(self.data[2 * index], self.data[2 * index + 1]) + self.lazy[index]
			index >>= 1

	def query(self, alpha, omega):
		res = self.default
		alpha += self.size
		omega += self.size + 1
		for i in range(len(bin(alpha)[2:]) - 1, 0, -1):
			self.push(alpha >> i)
		for i in range(len(bin(omega - 1)[2:]) - 1, 0, -1):
			self.push(omega - 1 >> i)
		while alpha < omega:
			if alpha & 1:
				res = self.func(res, self.data[alpha])
				alpha += 1
			if omega & 1:
				omega -= 1
				res = self.func(res, self.data[omega])
			alpha >>= 1
			omega >>= 1
		return res

	def update(self, alpha, omega, value):
		alpha += self.size
		omega += self.size + 1
		(l, r) = (alpha, omega)
		while alpha < omega:
			if alpha & 1:
				self.data[alpha] += value
				self.lazy[alpha] += value
				alpha += 1
			if omega & 1:
				omega -= 1
				self.data[omega] += value
				self.lazy[omega] += value
			alpha >>= 1
			omega >>= 1
		self.build(l)
		self.build(r - 1)
for _ in range(int(input()) if not True else 1):
	(n, m) = map(int, input().split())
	edges = []
	for i in range(n):
		(l, r, w) = map(int, input().split())
		edges += [(l, r, w)]
	edges = sorted(edges, key=lambda x: x[2])
	st = LazySegmentTree([0.0] * (2 * m + 1), func=min)
	i = j = 0
	ans = 10 ** 18
	st.update(2 * edges[0][0], 2 * edges[0][1], 1)
	while i < len(edges) and j < len(edges):
		if st.query(2, 2 * m):
			ans = min(ans, edges[j][2] - edges[i][2])
			st.update(2 * edges[i][0], 2 * edges[i][1], -1)
			i += 1
		else:
			j += 1
			if j < len(edges):
				st.update(2 * edges[j][0], 2 * edges[j][1], 1)
	print(ans)


from sys import stdin, stdout

class LazySegmentTree:

	def __init__(self, data, default=0, func=min):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self._lazy = [0] * (2 * _size)
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __len__(self):
		return self._len

	def _push(self, idx):
		(q, self._lazy[idx]) = (self._lazy[idx], 0)
		self._lazy[2 * idx] += q
		self._lazy[2 * idx + 1] += q
		self.data[2 * idx] += q
		self.data[2 * idx + 1] += q

	def _update(self, idx):
		for i in reversed(range(1, idx.bit_length())):
			self._push(idx >> i)

	def _build(self, idx):
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1]) + self._lazy[idx]
			idx >>= 1

	def add(self, start, stop, value):
		start = start_copy = start + self._size
		stop = stop_copy = stop + self._size
		while start < stop:
			if start & 1:
				self._lazy[start] += value
				self.data[start] += value
				start += 1
			if stop & 1:
				stop -= 1
				self._lazy[stop] += value
				self.data[stop] += value
			start >>= 1
			stop >>= 1
		self._build(start_copy)
		self._build(stop_copy - 1)

	def query(self, start, stop, default=10000000000.0):
		start += self._size
		stop += self._size
		self._update(start)
		self._update(stop - 1)
		res = default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'LazySegmentTree({0})'.format(self.data)
(n, m) = [int(x) for x in stdin.readline().split()]
segments = []
for i in range(n):
	segments.append([int(x) for x in stdin.readline().split()])
segments.sort(key=lambda x: x[2])
answer = 1000001
tree = LazySegmentTree([0] * (m - 1))
i = 0
j = 0
while i < n:
	while j < n:
		tree.add(segments[j][0] - 1, segments[j][1] - 1, 1)
		if tree.query(0, m - 1):
			answer = min(answer, segments[j][2] - segments[i][2])
			break
		else:
			j += 1
	tree.add(segments[i][0] - 1, segments[i][1] - 1, -1)
	i += 1
	while tree.query(0, m - 1):
		answer = min(answer, segments[j][2] - segments[i][2])
		tree.add(segments[i][0] - 1, segments[i][1] - 1, -1)
		i += 1
	j += 1
stdout.write(str(answer) + '\n')


import sys, os, io
import math
from collections import defaultdict
from io import BytesIO, IOBase
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def ii():
	return int(input())

def li():
	return list(map(int, input().split()))

class LazySegmentTree:

	def __init__(self, data, default=0, func=min):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self._lazy = [0] * (2 * _size)
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __len__(self):
		return self._len

	def _push(self, idx):
		(q, self._lazy[idx]) = (self._lazy[idx], 0)
		self._lazy[2 * idx] += q
		self._lazy[2 * idx + 1] += q
		self.data[2 * idx] += q
		self.data[2 * idx + 1] += q

	def _update(self, idx):
		for i in reversed(range(1, idx.bit_length())):
			self._push(idx >> i)

	def _build(self, idx):
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1]) + self._lazy[idx]
			idx >>= 1

	def add(self, start, stop, value):
		start = start_copy = start + self._size
		stop = stop_copy = stop + self._size
		while start < stop:
			if start & 1:
				self._lazy[start] += value
				self.data[start] += value
				start += 1
			if stop & 1:
				stop -= 1
				self._lazy[stop] += value
				self.data[stop] += value
			start >>= 1
			stop >>= 1
		self._build(start_copy)
		self._build(stop_copy - 1)

	def query(self, start, stop, default=10000000000.0):
		start += self._size
		stop += self._size
		self._update(start)
		self._update(stop - 1)
		res = default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'LazySegmentTree({0})'.format(self.data)
if os.path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
	input = lambda : sys.stdin.readline().rstrip('\r\n')
(n, m) = li()
a = []
for i in range(n):
	(l, r, w) = li()
	a.append([w, l - 1, r - 1])
a.sort()
ans = float('inf')
data = [0] * m
tree = LazySegmentTree(data)
right = 0
for left in range(n):
	while right < n and tree.query(0, m - 1) == 0:
		(w, le, re) = a[right]
		tree.add(le, re, 1)
		right += 1
	if tree.query(0, m - 1) == 1:
		ans = min(ans, a[right - 1][0] - a[left][0])
	(w, le, re) = a[left]
	tree.add(le, re, -1)
print(ans)