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 C (judge verdict: Accepted)

// AOJ 0302: Star Watching
// 2017.12.27 bal4u@uu

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 524290

#define MIN(a,b) ((a)<=(b)?(a):(b))

#define INF 0x11111111
typedef struct { int x, y, l; } T;
T tbl[MAX];
int seg[4][MAX], sz;
char buf[30], *p;

int in()
{
	int n = 0;
	while (*p >= '0') n = 10*n + (*p++ & 0xf);
	p++;
	return n;
}

#if 0
void segtree(int id, int n)
{
	int k;
	k = 1; while (k < n) k <<= 1;
	sz = k;
	memset(seg[id], INF, sizeof(seg[id]));
}
#endif

// update kth value to v
void update(int id, int k, int v)
{
//	int t;
	k += sz-1;
	seg[id][k] = v;
	while (k > 0) {
#if 0
		if (!(k & 1)) k--;
		t = k, k >>= 1;
		v = seg[id][t++]; if (v > seg[id][t]) v = seg[id][t];
		seg[id][k] = v;
#else
		k = (k-1)/2;
		seg[id][k] = MIN(seg[id][k*2+1], seg[id][k*2+2]);
#endif
	}
}

int query2(int id, int a, int b, int k, int l, int r) 
{
	int m, lmin, rmin;

	if (r <= a || b <= l) return INF;
    if (a <= l && r <= b) return seg[id][k];
#if 0
	k <<= 1, m = (l + r) >> 1;
    lmin = query2(id, a, b, ++k, l, m);
    rmin = query2(id, a, b, ++k, m, r);
    if (lmin > rmin) lmin = rmin; 
    return lmin;
#else
	m = (l + r) / 2;
	lmin = query2(id, a, b, k*2+1, l, m);
    rmin = query2(id, a, b, k*2+2, m, r);
	return MIN(lmin, rmin);
#endif
}

// get min in [a, b)
int query(int id, int a, int b)
{
	return query2(id, a, b+1, 0, 0, sz);
}

int cmp(T *a, T *b) { return a->l - b->l; }

int main()
{
	int n, d, i, j;
	long long ans, a;

	fgets(p=buf, 30, stdin);
	n = in(), d = in();
	for (i = 0; i < n; i++) {
		fgets(p=buf, 30, stdin);
		tbl[i].x = in(), tbl[i].y = in(), tbl[i].l = in();
	}
	qsort(tbl, n, sizeof(T), cmp);
	tbl[n].l = INF;

	sz = 1; while (sz < n) sz <<= 1;
	memset(seg, INF, sizeof(seg));

	for (i = 0; i < n; i++) {
		update(0, i, -tbl[i].x), update(1, i, tbl[i].x);
		update(2, i, -tbl[i].y), update(3, i, tbl[i].y);
	}

	ans = 0;
	for (j = i = 0; i < n; i++) {
		while (j < n && tbl[j].l - tbl[i].l <= d) j++;
		j--;

		a = (((long long)query(0, i, j)) + query(1, i, j)) *
			(((long long)query(2, i, j)) + query(3, i, j));
		if (a > ans) ans = a;

	}
	printf("%lld\n", ans);
	return 0;
}