Problem:
天体観測

ある晴れた夜の帰り道、空を見上げるとそこには無数の星。強く輝く星々、かすかに見える星々、いろ
いろな明るさの星々が夜空を彩っています。

あなたはふと思いました。この星空に自分の星座があったらどんなに素敵だろうと。そこであなたはひとつの基準を決め、部屋の窓から見える星々を適当につなげて自分の星座を作ることにしました。その基準とは、「どの２つの星を選んでも、それらの明るさの差がある定数 d 以下になるような星のグループを作り、その中で一番大きいものを自分の星座にしよう！」というものです。例えば、図のような窓から見える夜空を考えてみましょう（外側の長方形は窓枠です）。

この夜空には、明るさがそれぞれ 1，12, 2，4，1，8, 3，5，4 の９つの星がありますが、d = 2 とすると例えば以下のような３つの星座 A, B, C ができます。

大きさが 12 の星座 A

大きさが 10 の星座 B

大きさが 16 の星座 C

星座の大きさを次のように決めることにしました。ある星座の星をすべて含むような、窓枠に平行な辺からなる長方形のうち、面積が最も小さいものを選びます。この長方形の面積をその星座の大きさとします。例えば、上の夜空では星座 A, B, Cの大きさはそれぞれ12, 10, 16になるので、星座Cが最も大きい星座となります。

N 個の星の位置と明るさ、および整数 d が与えられたとき、一番大きい星座の面積を求めるプログラムを作成してください。星の位置は窓枠の左下隅を原点とした座標で与えられ、軸は図のような向きとします。星座を構成する星が１つの場合や、星々が軸に平行な直線上にある場合は、その星座の面積は 0 となることに注意してください。

入力

入力は以下の形式で与えられる。

N d
x1 y1 b1
x2 y2 b2
:
xN yN bN

1 行目に星の数 N (1 ≤ N ≤ 200000) と整数 d (0 ≤ d ≤ 109) が与えられる。続く N 行に、i 番目の星の座標を表す整数 xi (0 ≤ xi ≤ 2000000) と yi (0 ≤ yi ≤ 2000000)、明るさを表す整数 bi (0 ≤ bi ≤ 109) が与えられる。入力される星の座標はすべて異なる。

出力

一番大きい星座の面積を１行に出力する。

入出力例

入力例

9 2
1 1 1
1 5 12
2 3 2
3 2 4
4 4 1
5 1 3
5 3 8
6 5 5
7 2 4

出力例

16

Solution in Python3 (judge verdict: Wrong Answer)

def main():
  INF = 10 ** 20

  class MinTree:
    def __init__(self, iterable):
      self.iter_size = self.get_size(iterable)
      self.size = self.iter_size * 2 - 1
      self.value = [None] * self.size
      for i, v in enumerate(iterable):
        self.value[self.iter_size + i - 1] = v
      self.set_value(0)
      self.range = [None] * self.size
      self.set_range(0, 0, self.iter_size - 1)
 
    
    def get_size(self, iterable):
      ret = 1
      x = len(iterable)
      while ret < x:
        ret *= 2
      return ret

    def set_range(self, x, left, right):
      self.range[x] = (left, right)
      if left != right:
        self.set_range(x * 2 + 1, left, (right + left) // 2)
        self.set_range(x * 2 + 2, (right + left) // 2 + 1, right)

    def set_value(self, x):
      if x >= self.iter_size - 1:return self.value[x]
      a = self.set_value(x * 2 + 1)
      b = self.set_value(x * 2 + 2)
      if a == None and b == None:
        self.value[x] = None
      elif a == None:
        self.value[x] = b
      elif b == None:
        self.value[x] = a
      else:
        self.value[x] = a if a < b else b
      return self.value[x]
  
    def query(self, x, left, right):
      x_left, x_right = self.range[x]
      if right < x_left or x_right < left:
        return INF
      if left <= x_left and x_right <= right:
        return self.value[x]
  
      return min(self.query(x * 2 + 1, left, right), self.query(x * 2 + 2, left, right))
  
  
  class MaxTree:
    def __init__(self, iterable):
      self.iter_size = self.get_size(iterable)
      self.size = self.iter_size * 2 - 1
      self.value = [None] * self.size
      for i, v in enumerate(iterable):
        self.value[self.iter_size + i - 1] = v
      self.set_value(0)
      self.range = [None] * self.size
      self.set_range(0, 0, self.iter_size - 1)
    
    def get_size(self, iterable):
      ret = 1
      x = len(iterable)
      while ret < x:
        ret *= 2
      return ret
    
    def set_range(self, x, left, right):
      self.range[x] = (left, right)
      if left != right:
        self.set_range(x * 2 + 1, left, (right + left) // 2)
        self.set_range(x * 2 + 2, (right + left) // 2 + 1, right)


    def set_value(self, x):
      if x >= self.iter_size - 1:return self.value[x]
      a = self.set_value(x * 2 + 1)
      b = self.set_value(x * 2 + 2)
      if a == None and b == None:
        self.value[x] = None
      elif a == None:
        self.value[x] = b
      elif b == None:
        self.value[x] = a
      else:
        self.value[x] = a if a > b else b
      return self.value[x]
  
    def query(self, x, left, right):
      x_left, x_right = self.range[x]
      if right < x_left or x_right < left:
        return 0
      if left <= x_left and x_right <= right:
        return self.value[x]
  
      return max(self.query(x * 2 + 1, left, right), self.query(x * 2 + 2, left, right))
  
  from bisect import bisect_right as br

  n, d = map(int, input().split())
  lst = sorted([list(map(int, input().split())) for _ in range(n)], key=lambda x:x[2])
  sorted_x = []
  sorted_y = []
  keys = []
  for i in range(n):
    x, y, b = lst[i]
    sorted_x.append(x)
    sorted_y.append(y)
    keys.append(b)
  mxt = MinTree(sorted_x)
  Mxt = MaxTree(sorted_x)
  myt = MinTree(sorted_y)
  Myt = MaxTree(sorted_y)
  
  def score(left, right):
    return (Mxt.query(0, left, right) - mxt.query(0, left, right)) * \
           (Myt.query(0, left, right) - myt.query(0, left, right))
  
  left = 0
  right = br(keys, keys[0] + d) - 2
  mx = mxt.query(0, left, right)
  Mx = Mxt.query(0, left, right)
  my = myt.query(0, left, right)
  My = Myt.query(0, left, right)
  end = len(keys)
  ans = (Mx - mx) * (My - my)
  while True:
    right += 1
    if right == end:break
    
    if sorted_x[right] > Mx:Mx = sorted_x[right]
    if sorted_x[right] < mx:mx = sorted_x[right] 
    if sorted_y[right] > My:My = sorted_y[right]
    if sorted_y[right] < my:my = sorted_y[right]
    
    Mx_flag = mx_flag = My_flag = my_flag = False
    while keys[left] + d <= keys[right]:
      if sorted_x[left] == Mx:Mx_flag = True
      if sorted_x[left] == mx:mx_flag = True
      if sorted_y[left] == My:My_flag = True
      if sorted_y[left] == my:my_flag = True
      left += 1
    left -= 1
    
    if Mx_flag:Mx = Mxt.query(0, left, right)
    if mx_flag:mx = mxt.query(0, left, right)
    if My_flag:My = Myt.query(0, left, right)
    if my_flag:my = myt.query(0, left, right)
    
    ans = max(ans, (Mx - mx) * (My - my)) 
  
  print(ans)

main()