from atcoder.lazysegtree import LazySegTree def RangeMaxUpdatePointGetLST(n: int, e: int): # 値データ Data = int # 遅延データ Lazy = int # 値データを合成 (使わない) def op(a: Data, b: Data) -> Data: return 0 # 遅延データを値データに反映 : f(x) def mapping(f: Lazy, x: Data) -> Data: if f == e: return x return max(f, x) # 遅延データを伝搬 # 二つの遅延データを合成 : (f . g) def composition(f: Lazy, g: Lazy) -> Lazy: if f == e: return g return max(f, g) class C: def __init__(self, n): # 単位元 e : 全ての a に対して op(a, e) = op(e, a) = a を満たす # 恒等写像 id : 全ての a に対して mapping(id, a) = a を満たす self.segt = LazySegTree( op=op, e=e, mapping=mapping, composition=composition, id_=e, v=[e] * n) def range_max_update(self, l: int, r: int, x: int): """区間 [l, r) を x に変更する""" self.segt.apply(l, r, x) def point_get(self, p: int) -> int: """位置 p の要素を求める""" return self.segt.get(p) return C(n) N, T = map(int, input().split()) lsegt = RangeMaxUpdatePointGetLST(2 * 10**5 + 10, 0) xs = [] for _ in range(N): L, R, P = map(int, input().split()) lsegt.range_max_update(L, R+1, P) sz = 2 * 10**5 + T + 10 dp = [0] * sz for i in range(2 * 10**5 + 1): if i+T >= sz: break dp[i+1] = max(dp[i+1], dp[i]) dp[i+T] = max(dp[i+T], dp[i] + lsegt.point_get(i)) ans = max(dp) print(ans)