Problem:
G: 最小包含矩形 - Minimum Enclosing Rectangle -
物語
みんなぁ、こんにちは！　八森中ぷろこん部の藍座あいりだよぉ。
突然だけど、あいりがこの前解けなかった問題をみんなに解いて欲しいんだぁ～。
この前部活で
ICPC2010のA問題
を解いたんだけど、その時の問題が難しかったんだぁ。
あ、ICPCについて説明しなきゃ！　ICPCは、い、いんたーなしょなる……ちゅうがくせい……ぷろぐらみんぐ……こんてすとの略で、日本語に直すと、国際中学生対抗プログラミングコンテストらしいよぉ！ あいりにはちょっとむずかしい言葉がいっぱいだよぉ。
あいり達はこの世界大会に出るために毎日頑張ってるんだぁ！
部活から帰った後お姉ちゃんにも聞いてみたんだけど、「わ、わからないわ……A問題からわからないなんて……お姉ちゃん失格ね……」って落ち込んじゃって…… 
でも、「『プロ』の人たちが一杯集まるところを知ってるの、お姉ちゃんちょっと連絡してみるわ。あいり、そこで聞いてみなさい！」って言ってここの合宿を教えてもらったんだぁ～ 。
ここに集まる『プロ』のみんなには簡単かもしれないけど……この問題を解いてほしいの！
問題
長さが
1
の正方形が
N
個、
2
次元平面上にある。これら
N
個の正方形を全て内包する、最小面積の長方形を求めよ。
入力形式
入力は
N
行からなる。
N
n_1
d_1
n_2
d_2
n_3
d_3
...
n_{N − 1}
d_{N − 1}
最初の行には、正方形の個数
N
が与えられる。
以下
N − 1
行は、正方形の置き方を表している。そのうち上から
i
行目は、空白区切りで1つの整数
n_{i}
と1つの文字
d_{i}
が与えられる。これは
i
番目の正方形の置き方を指示している。ここで正方形の番号付けは、最初の正方形を
0
番目とし、その後置いた順番に
1
,
2
, ...,
N − 1
と番号付けられるものとする。
0
番目の正方形に対する置き方の指示はない。
i
番目の正方形に対する置き方の指示
n_i, d_i
は、
i
番目の正方形を
n_i
番目の正方形に対して
d_i
で示される方向に隣接して置くことを指示する。
ここで、
n_i
は
i
未満の非負整数である。また、
d_i
は
0,1,2,3
のいずれかの値をとり、それぞれ
d_i
の値が、
0
ならば左側、
1
ならば下側、
2
ならば右側、
3
ならば上側を表す。
以下にそれぞれの入力例に対応した最終的な正方形の配置を図示している。左から入力例1、入力例2、入力例3、入力例4の最終的な正方形の配置となっている。図中の番号は正方形の番号に相当する。また、図中の緑線は求める最小面積の長方形を示している。
制約
入力はすべて整数
1 ≤ N ≤ 100,000
1 ≤ n_i < i
(
1 ≤ i < N
)
0 ≤ d_i ≤ 3
(
1 ≤ i < N
)
既に正方形が置かれている位置に、新たな正方形を置くような指示は与えられない。
出力形式
与えられた
N
個の点を全て包含する最小面積の長方形の面積を1行で出力する。
出力には
10^{−5}
以上の誤差を含んではならない。
入力例1
1
出力例1
1
入力例2
5
0 0
0 1
0 2
0 3
出力例2
8
入力例3
12
0 0
1 0
2 0
3 1
4 1
5 1
6 2
7 2
8 2
9 3
10 3
出力例3
16
入力例4
10
0 2
1 2
2 2
3 2
2 1
5 1
6 1
7 1
8 1
出力例4
30

Submitted solutions:

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool operator<(const Point& a1, const Point& a2) {
	if (a2.py - a1.py > 0) return true;
	if (a1.py - a2.py > 0) return false;
	if (a2.px - a1.px > 0) return true;
	if (a1.px - a2.px > 0) return false;
	return false;
}

long long crs(Point a1, Point a2) {
	return a1.px * a2.py - a2.px * a1.py;
}

vector<Point> Convex(vector<Point> Poly) {
	sort(Poly.begin(), Poly.end());

	// Right Part
	vector<Point> Stack1 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack1.size() >= 2) {
			Point v1 = Stack1[Stack1.size() - 2];
			Point v2 = Stack1[Stack1.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) <= 0) Stack1.pop_back();
			else break;
		}
		Stack1.push_back(Poly[i]);
	}

	// Left Part
	vector<Point> Stack2 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack2.size() >= 2) {
			Point v1 = Stack2[Stack2.size() - 2];
			Point v2 = Stack2[Stack2.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) >= 0) Stack2.pop_back();
			else break;
		}
		Stack2.push_back(Poly[i]);
	}

	// Joint
	vector<Point> Return = Stack1;
	for (int i = (int)Stack2.size() - 2; i >= 1; i--) Return.push_back(Stack2[i]);
	return Return;
}

const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
const long double TEISUU = 3.14159265358979L / 2.0L;
long long N;
long long A[1 << 18], B[1 << 18];
long long X[1 << 18], Y[1 << 18];
long double Angle[1 << 18];

long double GetArea(Point p1, Point p2, Point p3, Point p4, long double val) {
	// Get Yoko1
	Point diff1 = p2 - p1;
	long double dst1 = sqrtl(1.0L * diff1.px * diff1.px + 1.0L * diff1.py * diff1.py);
	long double yoko1 = dst1 * cos(atan2l(diff1.py, diff1.px) - val);

	// Get Yoko2
	Point diff2 = p1 - p4;
	long double dst2 = sqrtl(1.0L * diff2.px * diff2.px + 1.0L * diff2.py * diff2.py);
	long double yoko2 = dst2 * cos(atan2l(diff2.py, diff2.px) - val);

	// Get Tate1
	long double tate1 = dst1 * sin(atan2l(diff1.py, diff1.px) - val);

	// Get Tate2
	Point diff3 = p3 - p2;
	long double dst3 = sqrt(1.0L * diff3.px * diff3.px + 1.0L * diff3.py * diff3.py);
	long double tate2 = dst3 * cos(atan2l(diff3.py, diff3.px) - (val + TEISUU));

	// Return
	return (yoko1 + yoko2) * (tate1 + tate2);
}

long double Tansaku(Point p1, Point p2, Point p3, Point p4, double Left, long double Rigt) {
	long double cl = Left, cr = Rigt, c1 = 0, c2 = 0, minx = 1.0e12L;
	minx = min(minx, GetArea(p1, p2, p3, p4, Left));
	minx = min(minx, GetArea(p1, p2, p3, p4, Rigt));
	for (int i = 0; i < 40; i++) {
		c1 = (cl + cl + cr) / 3.0L;
		c2 = (cl + cr + cr) / 3.0L;
		c2 = Rigt;
		long double v1 = GetArea(p1, p2, p3, p4, c1);
		long double v2 = GetArea(p1, p2, p3, p4, c2);
		minx = min(minx, min(v1, v2));
		if (v1 > v2) { v1 = c1; }
		else { v2 = c2; }
	}
	return minx;
}

int main() {
	// Step 1. Input
	cin >> N;
	for (int i = 1; i < N; i++) cin >> A[i] >> B[i];
	// for (int i = 1; i < N; i++) { A[i] = max(0, i - 4); B[i] = (i - 1) % 4; }
	for (int i = 1; i < N; i++) {
		X[i] = X[A[i]] + dx[B[i]];
		Y[i] = Y[A[i]] + dy[B[i]];
	}

	// Step 2. Convex
	vector<Point> V;
	for (int i = 0; i < N; i++) {
		V.push_back(Point{ X[i] + 0, Y[i] + 0 });
		V.push_back(Point{ X[i] + 0, Y[i] + 1 });
		V.push_back(Point{ X[i] + 1, Y[i] + 0 });
		V.push_back(Point{ X[i] + 1, Y[i] + 1 });
	}
	vector<Point> W = Convex(V);
	for (int i = 0; i < W.size(); i++) {
		Point v = W[i] - W[(i + W.size() - 1) % W.size()];
		Angle[i] = atan2(v.py, v.px);
		if (Angle[i] < 0.0L) Angle[i] += 4.0L * TEISUU;
	}

	// Step 3. Brute Force
	long double Answer = 1.0e12;
	for (int i = 0; i <= W.size(); i++) {
		for (int j = i + 1; j <= W.size(); j++) {
			for (int k = j + 1; k <= W.size(); k++) {
				for (int l = k + 1; l <= W.size(); l++) {
					long double cl = 0.0L - 1.0e-9L, cr = TEISUU + 1.0e-9L;
					if (i != 0) cl = max(cl, Angle[(i + 0) % W.size()]);
					cr = min(cr, Angle[(i + 1) % W.size()]);
					cl = max(cl, Angle[(j + 0) % W.size()] - 1.0L * TEISUU);
					cr = min(cr, Angle[(j + 1) % W.size()] - 1.0L * TEISUU);
					cl = max(cl, Angle[(k + 0) % W.size()] - 2.0L * TEISUU);
					cr = min(cr, Angle[(k + 1) % W.size()] - 2.0L * TEISUU);
					cl = max(cl, Angle[(l + 0) % W.size()] - 3.0L * TEISUU);
					if (l != W.size()) cr = min(cr, Angle[(l + 1) % W.size()] - 3.0L * TEISUU);
					if (cl > cr) continue;
					long double ret = Tansaku(W[i], W[j], W[k], W[l % W.size()], cl, cr);
					Answer = min(Answer, ret);
				}
			}
		}
	}

	// Step 4. Output
	printf("%.12Lf\n", Answer);
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 25708
final_rank: 9

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool operator<(const Point& a1, const Point& a2) {
	if (a2.py - a1.py > 0) return true;
	if (a1.py - a2.py > 0) return false;
	if (a2.px - a1.px > 0) return true;
	if (a1.px - a2.px > 0) return false;
	return false;
}

long long crs(Point a1, Point a2) {
	return a1.px * a2.py - a2.px * a1.py;
}

vector<Point> Convex(vector<Point> Poly) {
	sort(Poly.begin(), Poly.end());

	// Right Part
	vector<Point> Stack1 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack1.size() >= 2) {
			Point v1 = Stack1[Stack1.size() - 2];
			Point v2 = Stack1[Stack1.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) <= 0) Stack1.pop_back();
			else break;
		}
		Stack1.push_back(Poly[i]);
	}

	// Left Part
	vector<Point> Stack2 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack2.size() >= 2) {
			Point v1 = Stack2[Stack2.size() - 2];
			Point v2 = Stack2[Stack2.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) >= 0) Stack2.pop_back();
			else break;
		}
		Stack2.push_back(Poly[i]);
	}

	// Joint
	vector<Point> Return = Stack1;
	for (int i = (int)Stack2.size() - 2; i >= 1; i--) Return.push_back(Stack2[i]);
	return Return;
}

const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
const long double TEISUU = 3.14159265358979L / 2.0L;
long long N;
long long A[1 << 18], B[1 << 18];
long long X[1 << 18], Y[1 << 18];
long double Angle[1 << 18];

long double GetArea(Point p1, Point p2, Point p3, Point p4, long double val) {
	// Get Yoko1
	Point diff1 = p2 - p1;
	long double dst1 = sqrtl(1.0L * diff1.px * diff1.px + 1.0L * diff1.py * diff1.py);
	long double yoko1 = dst1 * cos(atan2l(diff1.py, diff1.px) - val);

	// Get Yoko2
	Point diff2 = p1 - p4;
	long double dst2 = sqrtl(1.0L * diff2.px * diff2.px + 1.0L * diff2.py * diff2.py);
	long double yoko2 = dst2 * cos(atan2l(diff2.py, diff2.px) - val);

	// Get Tate1
	long double tate1 = dst1 * sin(atan2l(diff1.py, diff1.px) - val);

	// Get Tate2
	Point diff3 = p3 - p2;
	long double dst3 = sqrt(1.0L * diff3.px * diff3.px + 1.0L * diff3.py * diff3.py);
	long double tate2 = dst3 * cos(atan2l(diff3.py, diff3.px) - (val + TEISUU));

	// Return
	return (yoko1 + yoko2) * (tate1 + tate2);
}

long double Tansaku(Point p1, Point p2, Point p3, Point p4, long double Left, long double Rigt) {
	long double minx = 1.0e12L;
	minx = min(minx, GetArea(p1, p2, p3, p4, Left));
	minx = min(minx, GetArea(p1, p2, p3, p4, Rigt));
	for (int t = 0; t < 10; t++) {
		long double cl = 0.1L * (10 - t) * Left + 0.1L * (t + 0) * Rigt;
		long double cr = 0.1L * ( 9 - t) * Left + 0.1L * (t + 1) * Rigt;
		long double c1 = 0, c2 = 0;
		for (int i = 0; i < 80; i++) {
			c1 = (cl + cl + cr) / 3.0L;
			c2 = (cl + cr + cr) / 3.0L;
			c2 = Rigt;
			long double v1 = GetArea(p1, p2, p3, p4, c1);
			long double v2 = GetArea(p1, p2, p3, p4, c2);
			minx = min(minx, min(v1, v2));
			if (v1 > v2) { v1 = c1; }
			else { v2 = c2; }
		}
	}
	return minx;
}

int main() {
	// Step 1. Input
	cin >> N;
	for (int i = 1; i < N; i++) cin >> A[i] >> B[i];
	// for (int i = 1; i < (N + 1) / 2; i++) { A[i] = i - 1; B[i] = 0; }
	// for (int i = (N + 1) / 2; i < N; i++) { A[i] = i - 1; B[i] = 1; }
	for (int i = 1; i < N; i++) {
		X[i] = X[A[i]] + dx[B[i]];
		Y[i] = Y[A[i]] + dy[B[i]];
	}

	// Step 2. Convex
	vector<Point> V;
	for (int i = 0; i < N; i++) {
		V.push_back(Point{ X[i] + 0, Y[i] + 0 });
		V.push_back(Point{ X[i] + 0, Y[i] + 1 });
		V.push_back(Point{ X[i] + 1, Y[i] + 0 });
		V.push_back(Point{ X[i] + 1, Y[i] + 1 });
	}
	vector<Point> W = Convex(V);
	for (int i = 0; i < W.size(); i++) {
		Point v = W[i] - W[(i + W.size() - 1) % W.size()];
		Angle[i] = atan2(v.py, v.px);
		if (Angle[i] < 0.0) Angle[i] += 4.0 * TEISUU;
	}

	// Step 3. Brute Force
	long double Answer = 1.0e12;
	for (int i = 0; i < W.size(); i++) {
		for (int j = i + 1; j < W.size(); j++) {
			for (int k = j + 1; k < W.size(); k++) {
				for (int l = k + 1; l < W.size(); l++) {
					long double cl = 0.0L - 1.0e-9L, cr = TEISUU + 1.0e-9L;
					if (i != 0) cl = max(cl, Angle[(i + 0) % W.size()]);
					cr = min(cr, Angle[(i + 1) % W.size()]);
					cl = max(cl, Angle[(j + 0) % W.size()] - 1.0 * TEISUU);
					cr = min(cr, Angle[(j + 1) % W.size()] - 1.0 * TEISUU);
					cl = max(cl, Angle[(k + 0) % W.size()] - 2.0 * TEISUU);
					cr = min(cr, Angle[(k + 1) % W.size()] - 2.0 * TEISUU);
					cl = max(cl, Angle[(l + 0) % W.size()] - 3.0 * TEISUU);
					cr = min(cr, Angle[(l + 1) % W.size()] - 3.0 * TEISUU);
					if (cl > cr) continue;
					long double ret = Tansaku(W[i], W[j], W[k], W[l], cl, cr);
					Answer = min(Answer, ret);
				}
			}
		}
	}

	// Step 4. Output
	printf("%.12Lf\n", Answer);
	return 0;
}
accuracy: 0.6233766233766234
time_ms: 90
memory_kb: 25088
final_rank: 20

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool operator<(const Point& a1, const Point& a2) {
	if (a2.py - a1.py > 0) return true;
	if (a1.py - a2.py > 0) return false;
	if (a2.px - a1.px > 0) return true;
	if (a1.px - a2.px > 0) return false;
	return false;
}

long long crs(Point a1, Point a2) {
	return a1.px * a2.py - a2.px * a1.py;
}

vector<Point> Convex(vector<Point> Poly) {
	sort(Poly.begin(), Poly.end());

	// Right Part
	vector<Point> Stack1 = { Poly[0], Poly[1]};
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack1.size() >= 2) {
			Point v1 = Stack1[Stack1.size() - 2];
			Point v2 = Stack1[Stack1.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) <= 0) Stack1.pop_back();
			else break;
		}
		Stack1.push_back(Poly[i]);
	}

	// Left Part
	vector<Point> Stack2 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack2.size() >= 2) {
			Point v1 = Stack2[Stack2.size() - 2];
			Point v2 = Stack2[Stack2.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) >= 0) Stack2.pop_back();
			else break;
		}
		Stack2.push_back(Poly[i]);
	}

	// Joint
	vector<Point> Return = Stack1;
	for (int i = (int)Stack2.size() - 2; i >= 1; i--) Return.push_back(Stack2[i]);
	return Return;
}

const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
const long double TEISUU = 3.14159265358979L / 2.0L;
long long N;
long long A[1 << 18], B[1 << 18];
long long X[1 << 18], Y[1 << 18];
long double Angle[1 << 18];

long double GetArea(Point p1, Point p2, Point p3, Point p4, long double val) {
	// Get Yoko1
	Point diff1 = p2 - p1;
	long double dst1 = sqrtl(1.0L * diff1.px * diff1.px + 1.0L * diff1.py * diff1.py);
	long double yoko1 = dst1 * cos(atan2l(diff1.py, diff1.px) - val);

	// Get Yoko2
	Point diff2 = p1 - p4;
	long double dst2 = sqrtl(1.0L * diff2.px * diff2.px + 1.0L * diff2.py * diff2.py);
	long double yoko2 = dst2 * cos(atan2l(diff2.py, diff2.px) - val);
	
	// Get Tate1
	long double tate1 = dst1 * sin(atan2l(diff1.py, diff1.px) - val);

	// Get Tate2
	Point diff3 = p3 - p2;
	long double dst3 = sqrt(1.0L * diff3.px * diff3.px + 1.0L * diff3.py * diff3.py);
	long double tate2 = dst3 * cos(atan2l(diff3.py, diff3.px) - (val + TEISUU));

	// Return
	return (yoko1 + yoko2) * (tate1 + tate2);
}

long double Tansaku(Point p1, Point p2, Point p3, Point p4, long double Left, long double Rigt) {
	long double cl = Left, cr = Rigt, c1 = 0, c2 = 0, minx = 1.0e12L;
	minx = min(minx, GetArea(p1, p2, p3, p4, Left));
	minx = min(minx, GetArea(p1, p2, p3, p4, Rigt));
	for (int i = 0; i < 80; i++) {
		c1 = (cl + cl + cr) / 3.0L;
		c2 = (cl + cr + cr) / 3.0L;
		c2 = Rigt;
		long double v1 = GetArea(p1, p2, p3, p4, c1);
		long double v2 = GetArea(p1, p2, p3, p4, c2);
		minx = min(minx, min(v1, v2));
		if (v1 > v2) { v1 = c1; }
		else { v2 = c2; }
	}
	return minx;
}

int main() {
	// Step 1. Input
	cin >> N;
	for (int i = 1; i < N; i++) cin >> A[i] >> B[i];
	for (int i = 1; i < N; i++) {
		X[i] = X[A[i]] + dx[B[i]];
		Y[i] = Y[A[i]] + dy[B[i]];
	}

	// Step 2. Convex
	vector<Point> V;
	for (int i = 0; i < N; i++) {
		V.push_back(Point{ X[i] + 0, Y[i] + 0 });
		V.push_back(Point{ X[i] + 0, Y[i] + 1 });
		V.push_back(Point{ X[i] + 1, Y[i] + 0 });
		V.push_back(Point{ X[i] + 1, Y[i] + 1 });
	}
	vector<Point> W = Convex(V);
	for (int i = 0; i < W.size(); i++) {
		Point v = W[i] - W[(i + W.size() - 1) % W.size()];
		Angle[i] = atan2(v.py, v.px);
		if (Angle[i] < 0.0) Angle[i] += 4.0 * TEISUU;
	}

	// Step 3. Brute Force
	long double Answer = 1.0e12;
	for (int i = 0; i < W.size(); i++) {
		for (int j = i + 1; j < W.size(); j++) {
			for (int k = j + 1; k < W.size(); k++) {
				for (int l = k + 1; l < W.size(); l++) {
					long double cl = 0.0L - 1.0e-9L, cr = TEISUU + 1.0e-9L;
					if (i != 0) cl = max(cl, Angle[(i + 0) % W.size()]);
					cr = min(cr, Angle[(i + 1) % W.size()]);
					cl = max(cl, Angle[(j + 0) % W.size()] - 1.0 * TEISUU);
					cr = min(cr, Angle[(j + 1) % W.size()] - 1.0 * TEISUU);
					cl = max(cl, Angle[(k + 0) % W.size()] - 2.0 * TEISUU);
					cr = min(cr, Angle[(k + 1) % W.size()] - 2.0 * TEISUU);
					cl = max(cl, Angle[(l + 0) % W.size()] - 3.0 * TEISUU);
					cr = min(cr, Angle[(l + 1) % W.size()] - 3.0 * TEISUU);
					if (cl > cr) continue;
					long double ret = Tansaku(W[i], W[j], W[k], W[l], cl, cr);
					Answer = min(Answer, ret);
				}
			}
		}
	}

	// Step 4. Output
	printf("%.12Lf\n", Answer);
	return 0;
}
accuracy: 0.6233766233766234
time_ms: 60
memory_kb: 25316
final_rank: 19

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool operator<(const Point& a1, const Point& a2) {
	if (a2.py - a1.py > 0) return true;
	if (a1.py - a2.py > 0) return false;
	if (a2.px - a1.px > 0) return true;
	if (a1.px - a2.px > 0) return false;
	return false;
}

long long crs(Point a1, Point a2) {
	return a1.px * a2.py - a2.px * a1.py;
}

vector<Point> Convex(vector<Point> Poly) {
	sort(Poly.begin(), Poly.end());

	// Right Part
	vector<Point> Stack1 = { Poly[0], Poly[1]};
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack1.size() >= 2) {
			Point v1 = Stack1[Stack1.size() - 2];
			Point v2 = Stack1[Stack1.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) <= 0) Stack1.pop_back();
			else break;
		}
		Stack1.push_back(Poly[i]);
	}

	// Left Part
	vector<Point> Stack2 = { Poly[0], Poly[1] };
	for (int i = 2; i < Poly.size(); i++) {
		while (Stack2.size() >= 2) {
			Point v1 = Stack2[Stack2.size() - 2];
			Point v2 = Stack2[Stack2.size() - 1];
			Point v3 = Poly[i];
			if (crs(v2 - v1, v3 - v2) >= 0) Stack2.pop_back();
			else break;
		}
		Stack2.push_back(Poly[i]);
	}

	// Joint
	vector<Point> Return = Stack1;
	for (int i = (int)Stack2.size() - 2; i >= 1; i--) Return.push_back(Stack2[i]);
	return Return;
}

const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
const double TEISUU = 3.14159265358979 / 2.0;
long long N;
long long A[1 << 18], B[1 << 18];
long long X[1 << 18], Y[1 << 18];
double Angle[1 << 18];

double GetArea(Point p1, Point p2, Point p3, Point p4, double val) {
	// Get Yoko1
	Point diff1 = p2 - p1;
	double dst1 = sqrt(diff1.px * diff1.px + diff1.py * diff1.py);
	double yoko1 = dst1 * cos(atan2(diff1.py, diff1.px) - val);

	// Get Yoko2
	Point diff2 = p1 - p4;
	double dst2 = sqrt(diff2.px * diff2.px + diff2.py * diff2.py);
	double yoko2 = dst2 * cos(atan2(diff2.py, diff2.px) - val);
	
	// Get Tate1
	double tate1 = dst1 * sin(atan2(diff1.py, diff1.px) - val);

	// Get Tate2
	Point diff3 = p3 - p2;
	double dst3 = sqrt(diff3.px * diff3.px + diff3.py * diff3.py);
	double tate2 = dst3 * cos(atan2(diff3.py, diff3.px) - (val + TEISUU));

	// Return
	return (yoko1 + yoko2) * (tate1 + tate2);
}

double Tansaku(Point p1, Point p2, Point p3, Point p4, double Left, double Rigt) {
	double cl = Left, cr = Rigt, c1 = 0, c2 = 0, minx = 1e12;
	minx = min(minx, GetArea(p1, p2, p3, p4, Left));
	minx = min(minx, GetArea(p1, p2, p3, p4, Rigt));
	for (int i = 0; i < 40; i++) {
		c1 = (cl + cl + cr) / 3.0;
		c2 = (cl + cr + cr) / 3.0;
		c2 = Rigt;
		double v1 = GetArea(p1, p2, p3, p4, c1);
		double v2 = GetArea(p1, p2, p3, p4, c2);
		minx = min(minx, min(v1, v2));
		if (v1 > v2) { v1 = c1; }
		else { v2 = c2; }
	}
	return minx;
}

int main() {
	// Step 1. Input
	cin >> N;
	for (int i = 1; i < N; i++) cin >> A[i] >> B[i];
	for (int i = 1; i < N; i++) {
		X[i] = X[A[i]] + dx[B[i]];
		Y[i] = Y[A[i]] + dy[B[i]];
	}

	// Step 2. Convex
	vector<Point> V;
	for (int i = 0; i < N; i++) {
		V.push_back(Point{ X[i] + 0, Y[i] + 0 });
		V.push_back(Point{ X[i] + 0, Y[i] + 1 });
		V.push_back(Point{ X[i] + 1, Y[i] + 0 });
		V.push_back(Point{ X[i] + 1, Y[i] + 1 });
	}
	vector<Point> W = Convex(V);
	for (int i = 0; i < W.size(); i++) {
		Point v = W[i] - W[(i + W.size() - 1) % W.size()];
		Angle[i] = atan2(v.py, v.px);
		if (Angle[i] < 0.0) Angle[i] += 4.0 * TEISUU;
	}

	// Step 3. Brute Force
	double Answer = 1.0e12;
	for (int i = 0; i < W.size(); i++) {
		for (int j = i + 1; j < W.size(); j++) {
			for (int k = j + 1; k < W.size(); k++) {
				for (int l = k + 1; l < W.size(); l++) {
					double cl = 0 - 1.0e-8, cr = TEISUU + 1.0e-8;
					if (i != 0) cl = max(cl, Angle[(i + 0) % W.size()]);
					cr = min(cr, Angle[(i + 1) % W.size()]);
					cl = max(cl, Angle[(j + 0) % W.size()] - 1.0 * TEISUU);
					cr = min(cr, Angle[(j + 1) % W.size()] - 1.0 * TEISUU);
					cl = max(cl, Angle[(k + 0) % W.size()] - 2.0 * TEISUU);
					cr = min(cr, Angle[(k + 1) % W.size()] - 2.0 * TEISUU);
					cl = max(cl, Angle[(l + 0) % W.size()] - 3.0 * TEISUU);
					cr = min(cr, Angle[(l + 1) % W.size()] - 3.0 * TEISUU);
					if (cl > cr) continue;
					double ret = Tansaku(W[i], W[j], W[k], W[l], cl, cr);
					Answer = min(Answer, ret);
				}
			}
		}
	}

	// Step 4. Output
	printf("%.12lf\n", Answer);
	return 0;
}
accuracy: 0.6233766233766234
time_ms: 60
memory_kb: 25252
final_rank: 18

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};


Point input[SIZE],work[SIZE];

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

Polygon ConvexHull(Polygon V){

	sort(V.begin(),V.end());

	vector<Point> UP,DOWN;

	UP.push_back(V[0]);
	DOWN.push_back(V[0]);

	for(int i = 1; i < V.size(); i++){

		while(UP.size() > 1 && ccw(UP[UP.size()-2],UP[UP.size()-1],V[i]) == COUNTER_CLOCKWISE){

			UP.pop_back();
		}

		while(DOWN.size() > 1 && ccw(DOWN[DOWN.size()-2],DOWN[DOWN.size()-1],V[i]) ==  CLOCKWISE){

			DOWN.pop_back();
		}

		UP.push_back(V[i]);
		DOWN.push_back(V[i]);
	}

	Polygon ret;

	for(int i = 0; i < UP.size(); i++){

		ret.push_back(UP[i]);
	}

	for(int i = DOWN.size()-1; i >= 0; i--){ //★indexに注意★

		ret.push_back(DOWN[i]);
	}

	return ret;
}


//点のradを求める関数
double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}


/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

int main(){

	int N;
	scanf("%d",&N);

	if(N == 1){

		printf("1\n");
		return 0;
	}

	input[0] = Point(0,0); //左下の点

	int n,d;

	for(int i = 1; i <= N-1; i++){

		scanf("%d %d",&n,&d);

		switch(d){
		case 0: //左

			input[i] = Point(input[n].x-1,input[n].y);
			break;

		case 1: //下

			input[i] = Point(input[n].x,input[n].y-1);

			break;

		case 2: //右

			input[i] = Point(input[n].x+1,input[n].y);

			break;

		case 3: //上

			input[i] = Point(input[n].x,input[n].y+1);
			break;
		}
	}

	vector<Point> vec;
	for(int i = 0; i < N; i++){

		vec.push_back(input[i]);
		vec.push_back(Point(input[i].x+1,input[i].y));
		vec.push_back(Point(input[i].x+1,input[i].y+1));
		vec.push_back(Point(input[i].x,input[i].y+1));
	}
	sort(vec.begin(),vec.end());
	vec.erase(unique(vec.begin(),vec.end()),vec.end());

	Polygon ret = ConvexHull(vec);
	ret.pop_back();


	Polygon CH;
	CH.push_back(ret[0]);

	for(int i = 0; i < ret.size(); i++){
		if(i+1 < ret.size()){

			double pre_slope = calc_slope(Line(ret[i-1],ret[i]));
			double now_slope = calc_slope(Line(ret[i+1],ret[i]));

			if(fabs(pre_slope-now_slope) < EPS){

				continue;
			}

			CH.push_back(ret[i]);

		}else{

			CH.push_back(ret[i]);
		}
	}
	double ans = HUGE_NUM;

	int M = CH.size();

	int start = -1;
	double bottom = HUGE_NUM;
	for(int i = 0; i < M; i++){

		if(CH[i].y < bottom){
			bottom = CH[i].y;
			start = i;
		}
	}

	for(int i = 0; i < M; i++){

		work[i] = CH[i];
	}

	bool pre_Hori = false;

	for(int a = 0; a < M; a++){

		int i = (start+a)%M;

		double tmp_rad = calc_rad(work[(i+1)%M]-work[i]);

		Point base = work[i];

		if(fabs(tmp_rad-M_PI) < EPS || fabs(tmp_rad) < EPS){ //回転不要

			if(pre_Hori){

				continue;
			}else{

				pre_Hori = true;
			}
		}else{

			pre_Hori = false;
		}

		for(int k = 0; k < M; k++){
			if(k == i){

				continue;
			}
			Point tmp_p = rotate(base,work[k],-tmp_rad);
			work[k] = tmp_p;
		}

		double min_x = HUGE_NUM,max_x = -HUGE_NUM,min_y = HUGE_NUM,max_y = -HUGE_NUM;

		for(int k = 0; k < M; k++){

			min_x = min(min_x,work[k].x);
			max_x = max(max_x,work[k].x);

			min_y = min(min_y,work[k].y);
			max_y = max(max_y,work[k].y);
		}

		ans = min(ans,(max_x-min_x)*(max_y-min_y));
	}

	printf("%.12lf\n",ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 27160
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};


Point input[SIZE],work[SIZE];

double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

Polygon ConvexHull(Polygon V){

	sort(V.begin(),V.end());

	vector<Point> UP,DOWN;

	UP.push_back(V[0]);
	DOWN.push_back(V[0]);

	for(int i = 1; i < V.size(); i++){

		while(UP.size() > 1 && ccw(UP[UP.size()-2],UP[UP.size()-1],V[i]) == COUNTER_CLOCKWISE){

			UP.pop_back();
		}

		while(DOWN.size() > 1 && ccw(DOWN[DOWN.size()-2],DOWN[DOWN.size()-1],V[i]) ==  CLOCKWISE){

			DOWN.pop_back();
		}

		UP.push_back(V[i]);
		DOWN.push_back(V[i]);
	}

	Polygon ret;

	for(int i = 0; i < UP.size(); i++){

		ret.push_back(UP[i]);
	}

	for(int i = DOWN.size()-1; i >= 0; i--){ //★indexに注意★

		ret.push_back(DOWN[i]);
	}

	return ret;
}


//点のradを求める関数
double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}


/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

int main(){

	int N;
	scanf("%d",&N);

	if(N == 1){

		printf("1\n");
		return 0;
	}

	input[0] = Point(0,0); //左下の点

	int n,d;

	for(int i = 1; i <= N-1; i++){

		scanf("%d %d",&n,&d);

		switch(d){
		case 0: //左

			input[i] = Point(input[n].x-1,input[n].y);
			break;

		case 1: //下

			input[i] = Point(input[n].x,input[n].y-1);

			break;

		case 2: //右

			input[i] = Point(input[n].x+1,input[n].y);

			break;

		case 3: //上

			input[i] = Point(input[n].x,input[n].y+1);
			break;
		}
	}

	vector<Point> vec;
	for(int i = 0; i < N; i++){

		vec.push_back(input[i]);
		vec.push_back(Point(input[i].x+1,input[i].y));
		vec.push_back(Point(input[i].x+1,input[i].y+1));
		vec.push_back(Point(input[i].x,input[i].y+1));
	}
	sort(vec.begin(),vec.end());
	vec.erase(unique(vec.begin(),vec.end()),vec.end());

	Polygon ret = ConvexHull(vec);
	ret.pop_back();


	Polygon CH;
	CH.push_back(ret[0]);

	for(int i = 0; i < ret.size(); i++){
		if(i+1 < ret.size()){

			double pre_slope = calc_slope(Line(ret[i-1],ret[i]));
			double now_slope = calc_slope(Line(ret[i+1],ret[i]));

			if(fabs(pre_slope-now_slope) < EPS){

				continue;
			}

			CH.push_back(ret[i]);

		}else{

			CH.push_back(ret[i]);
		}
	}

	bool DEBUG = false;
	if(DEBUG){

		for(int i = 0; i < CH.size(); i++){

			CH[i].debug();
		}
	}

	double ans = HUGE_NUM;

	int M = CH.size();

	int start = -1;
	double bottom = HUGE_NUM;
	for(int i = 0; i < M; i++){

		if(CH[i].y < bottom){
			bottom = CH[i].y;
			start = i;
		}
	}

	for(int i = 0; i < M; i++){

		work[i] = CH[i];
	}

	bool pre_Hori = false;

	for(int a = 0; a < M; a++){

		int i = (start+a)%M;

		if(DEBUG){

			printf("\ni:%d\n",i);
			printf("基準点");
			CH[i].debug();
			printf("次の点");
			CH[(i+1)%M].debug();
		}

		double tmp_rad = calc_rad(work[(i+1)%M]-work[i]);

		if(DEBUG){

			printf("\ntmp_rad:%.3lf\n",tmp_rad);
		}

		Point base = work[i];

		if(fabs(tmp_rad-M_PI) < EPS || fabs(tmp_rad) < EPS){ //回転不要

			if(pre_Hori){

				continue;
			}else{

				pre_Hori = true;
			}
		}else{

			pre_Hori = false;
		}

		for(int k = 0; k < M; k++){
			if(k == i){

				continue;
			}
			Point tmp_p = rotate(base,work[k],-tmp_rad);
			work[k] = tmp_p;
		}

		if(DEBUG){

			printf("work[i]");
			work[i].debug();

			printf("work[i+1]");
			work[(i+1)%M].debug();
		}

		double min_x = HUGE_NUM,max_x = -HUGE_NUM,min_y = HUGE_NUM,max_y = -HUGE_NUM;

		for(int k = 0; k < M; k++){

			min_x = min(min_x,work[k].x);
			max_x = max(max_x,work[k].x);

			min_y = min(min_y,work[k].y);
			max_y = max(max_y,work[k].y);
		}

		ans = min(ans,(max_x-min_x)*(max_y-min_y));
	}

	printf("%.12lf\n",ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 27160
final_rank: 6

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
#include <complex>
#include <chrono>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>


struct Vector {
	double x, y;
	double rad() const {
		return std::atan2(y, x);
	}
	double cross(const Vector other) const {
		return x * other.y - y * other.x;
	}
	Vector rotate90() const {
		return Vector{ y, -x };
	}
	double length() const {
		return std::sqrt(x * x + y * y);
	}
	double dot(const Vector other) const {
		return x * other.x + y * other.y;
	}
	Vector to_len1() const {
		const auto len = length();
		return Vector{ x / len, y / len };
	}
};
struct Point {
	int x, y;
	Vector operator-(const Point other) const {
		return Vector{ double(x) - other.x, double(y) - other.y };
	}
	Point operator+(const Point other) const {
		return Point{ x + other.x, y + other.y };
	}
};

double solve(std::vector<Point> point) {
	if (point.size() == 1) return 1;
	std::sort(point.begin(), point.end(), [](const Point a, const Point b) {return a.y == b.y ? a.x < b.x : a.y > b.y; });
	std::vector<Point> convex{ point[0], point[1] };
	for (auto i = 2; i < point.size(); ++i) {
		int last = convex.size() - 1;
		while (convex.size() >= 2 && (convex[last] - convex[last - 1]).cross(point[i] - convex[last - 1]) >= 0) {
			convex.pop_back();
			--last;
		}
		convex.push_back(point[i]);
	}
	for (int i = point.size() - 2; i >= 0; --i) {
		int last = convex.size() - 1;
		while (convex.size() >= 2 && (convex[last] - convex[last - 1]).cross(point[i] - convex[last - 1]) >= 0) {
			convex.pop_back();
			--last;
		}
		convex.push_back(point[i]);
	}
	convex.pop_back();
	std::vector<int> indices{ 0, 
		(int)std::distance(convex.begin(), std::max_element(convex.begin(), convex.end(), [](const Point a, const Point b) {return a.x < b.x; })),
		(int)std::distance(convex.begin(), std::min_element(convex.begin(), convex.end(), [](const Point a, const Point b) {return a.y < b.y; })),
		(int)std::distance(convex.begin(), std::min_element(std::next(convex.begin()), convex.end(), [](const Point a, const Point b) {return a.x < b.x; })) };
	double result{ DBL_MAX };
	for (; indices[0] < convex.size(); ++indices[0]) {
		auto vec = convex[(indices[0] + 1) % convex.size()] - convex[indices[0]];
		const auto v = vec.to_len1();
		for (auto i = 1; i < 4; ++i) {
			vec = vec.rotate90();
			auto& idx = indices[i];
			while (vec.cross(convex[(idx + 1) % convex.size()] - convex[idx]) > 0) {
				idx = (idx + 1) % convex.size();
			}
		}
		const auto height = (convex[indices[2]] - convex[indices[0]]).dot(v.rotate90());
		const auto width = (convex[indices[1]] - convex[indices[3]]).dot(v);
		const auto area = height * width;
		result = std::min(result, area);
	}
	return result;
}

int main() {
	int n; std::cin >> n;
	std::vector<Point> point{ Point{0, 0} }; point.reserve(n << 2);
	std::array<Point, 4> dir{ Point{-1, 0}, Point{0, 1}, Point{1, 0}, Point{0, -1} };
	while (point.size() < n) {
		int x, d; std::cin >> x >> d;
		point.push_back(point[x] + dir[d]);
	}
	std::unordered_map<int, std::unordered_set<int>> coordinates;
	for (const auto [x, y] : point) {
		coordinates[x].insert(y);
		coordinates[x].insert(y + 1);
		coordinates[x + 1].insert(y);
		coordinates[x + 1].insert(y + 1);
	}
	point.clear();
	for (const auto& [x, ys] : coordinates) {
		for (const auto y : ys) {
			point.push_back(Point{ x, y });
		}
	}
	const auto result = solve(std::move(point));
	std::cout << std::setprecision(15) << std::fixed << result << '\n';
}
accuracy: 1
time_ms: 50
memory_kb: 24072
final_rank: 4

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
#include <complex>
#include <chrono>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>


struct Vector {
	double x, y;
	double rad() const {
		return std::atan2(y, x);
	}
	double cross(const Vector other) const {
		return x * other.y - y * other.x;
	}
	Vector rotate90() const {
		return Vector{ y, -x };
	}
	double length() const {
		return std::sqrt(x * x + y * y);
	}
	double dot(const Vector other) const {
		return x * other.x + y * other.y;
	}
	Vector to_len1() const {
		const auto len = length();
		return Vector{ x / len, y / len };
	}
};
struct Point {
	int x, y;
	Vector operator-(const Point other) const {
		return Vector{ double(x) - other.x, double(y) - other.y };
	}
	Point operator+(const Point other) const {
		return Point{ x + other.x, y + other.y };
	}
};

double solve(std::vector<Point> point) {
	if (point.size() == 1) return 1;
	std::sort(point.begin(), point.end(), [](const Point a, const Point b) {return a.y == b.y ? a.x < b.x : a.y > b.y; });
	std::vector<Point> convex{ point[0], point[1] };
	for (auto i = 2; i < point.size(); ++i) {
		int last = convex.size() - 1;
		while (convex.size() >= 2 && (convex[last] - convex[last - 1]).cross(point[i] - convex[last - 1]) >= 0) {
			convex.pop_back();
			--last;
		}
		convex.push_back(point[i]);
	}
	for (int i = point.size() - 2; i >= 0; --i) {
		int last = convex.size() - 1;
		while (convex.size() >= 2 && (convex[last] - convex[last - 1]).cross(point[i] - convex[last - 1]) >= 0) {
			convex.pop_back();
			--last;
		}
		convex.push_back(point[i]);
	}
	std::vector<int> indices{ 0, 
		(int)std::distance(convex.begin(), std::max_element(convex.begin(), convex.end(), [](const Point a, const Point b) {return a.x < b.x; })),
		(int)std::distance(convex.begin(), std::min_element(convex.begin(), convex.end(), [](const Point a, const Point b) {return a.y < b.y; })),
		(int)std::distance(convex.begin(), std::min_element(std::next(convex.begin()), convex.end(), [](const Point a, const Point b) {return a.x < b.x; })) };
	double result{ DBL_MAX };
	while (indices.back() + 1 < convex.size()) {
		std::vector<Vector> vec;
		for (const auto idx : indices) {
			vec.push_back(convex[idx + 1] - convex[idx]);
			for (auto& v : vec) {
				v = v.rotate90();
			}
		}
		const auto max = std::distance(vec.begin(), std::max_element(vec.begin(), vec.end(), [](const Vector a, const Vector b) {return a.rad() < b.rad(); }));
		auto v = vec[max].to_len1();
		const auto height = (convex[indices[2]] - convex[indices[0]]).dot(v.rotate90());
		const auto width = (convex[indices[1]] - convex[indices[3]]).dot(v);
		result = std::min(result, height * width);
		++indices[max];
	}
	return result;
}

int main() {
	int n; std::cin >> n;
	std::vector<Point> point{ Point{0, 0} }; point.reserve(n << 2);
	std::array<Point, 4> dir{ Point{-1, 0}, Point{0, 1}, Point{1, 0}, Point{0, -1} };
	while (point.size() < n) {
		int x, d; std::cin >> x >> d;
		point.push_back(point[x] + dir[d]);
	}
	std::unordered_map<int, std::unordered_set<int>> coordinates;
	for (const auto [x, y] : point) {
		coordinates[x].insert(y);
		coordinates[x].insert(y + 1);
		coordinates[x + 1].insert(y);
		coordinates[x + 1].insert(y + 1);
	}
	point.clear();
	for (const auto& [x, ys] : coordinates) {
		for (const auto y : ys) {
			point.push_back(Point{ x, y });
		}
	}
	const auto result = solve(std::move(point));
	std::cout << std::setprecision(15) << std::fixed << result << '\n';
}
accuracy: 0.6233766233766234
time_ms: 50
memory_kb: 11240
final_rank: 17

code_snippet: #include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <complex>
#include <set>
using namespace std;

using W = double;
using P = complex<W>;
using L = pair<P,P>;
using C = pair<P,W>;
using Poly = vector<P>;
#define X real()
#define Y imag()
const W EPS = (1e-10), pi = acos(-1);

namespace std{
  bool operator < (const P& a, const P& b){
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
  bool cmp_y(const P &a, const P &b){
    return a.Y != b.Y ? a.Y < b.Y : a.X < b.X;
  }
  bool operator == (const P& a, const P& b){
    return abs(a-b) < EPS;
  }
}

double dot(P a, P b){ return a.X * b.X + a.Y * b.Y;}
W cross(P a, P b){ return a.X * b.Y - a.Y * b.X;}

Poly convex_hull(Poly v){
  int n = v.size(), k = 0;
  sort(v.begin(), v.end(), cmp_y);
  Poly r(2*n);
  for(int i = 0; i < n; i++){
    while(k>1 && cross(r[k-1]-r[k-2],v[i]-r[k-2]) < -EPS) k--;
    r[k++] = v[i];
  }
  for(int i = n-2, t = k; i >= 0; i--){
    while(k>t && cross(r[k-1]-r[k-2],v[i]-r[k-2]) < -EPS) k--;
    r[k++] = v[i];
  }
  r.resize(k-1);
  return r;
}

int main(){
  int N;
  cin >> N;
  int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1};
  set<P> s;

  vector<P> sq = {{0,0},{1,0},{1,1},{0,1}};
  vector<vector<P>> D(N);
  D[0] = sq;
  for(int i = 1; i < N; ++i){
    int n, d;
    cin >> n >> d;
    vector<P> t = D[n];
    for(auto& p : t)
      p = p+P(dx[d],dy[d]);
    D[i] = t;
  }
  for(int i = 0; i < N; ++i){
    for(auto p : D[i])
      s.insert(p);
  }

  vector<P> ps;
  for(auto p : s)
    ps.push_back(p);
  vector<P> c = convex_hull(ps);

  // for(auto p : c)
  //   fprintf(stderr,"%lld %lld\n",p.X,p.Y);
  
  int v = c.size();
  int l = 0, r = 0, b = 0;
  P d = c[1] - c[0];
  P n(-d.Y,d.X);
  while(dot(d,c[(l+1)%v]-c[0]) >= dot(d,c[l]-c[0])){
    ++l;
    l %= v;
  }
  while(dot(d,c[(r+v-1)%v]-c[0]) <= dot(d,c[r]-c[0])){
    r = (r+v-1)%v;
  }
  while(dot(n,c[(b+1)%v]-c[0]) >= dot(n,c[b]-c[0])){
    b += 1;
    b %= v;
  }
  double ans = 1e18;
  for(int i = 0; i < v; ++i){
    d = c[(i+1)%v] - c[i];
    n = {-d.Y,d.X};
    while(dot(d,c[(l+1)%v]-c[i]) >= dot(d,c[l]-c[i])){
      ++l;
      l %= v;
    }
    while(dot(d,c[(r+1)%v]-c[i]) <= dot(d,c[r]-c[i])){
      ++r;
      r %= v;
    }
    while(dot(n,c[(b+1)%v]-c[i]) >= dot(n,c[b]-c[i])){
      ++b;
      b %= v;
    }
    // fprintf(stderr,"--------------------\n");
    // fprintf(stderr,"top    : (%lld,%lld) - (%lld,%lld)\n",c[(i+1)%v].X,c[(i+1)%v].Y,c[i].X,c[i].Y);
    // fprintf(stderr,"left   : (%lld,%lld)\n",c[l].X,c[l].Y);
    // fprintf(stderr,"bottom : (%lld,%lld)\n",c[b].X,c[b].Y);
    // fprintf(stderr,"right  : (%lld,%lld)\n",c[r].X,c[r].Y);
    // fprintf(stderr,"area   : %lld\n",dot(n,c[b]-c[i])*(dot(d,c[l]-c[i])-dot(d,c[r]-c[i]))/norm(d));
    // fprintf(stderr,"--------------------\n");
    ans = min(ans,dot(n,c[b]-c[i])*(dot(d,c[l]-c[i])-dot(d,c[r]-c[i]))/norm(d));
  }
  printf("%.12f\n",ans);
}
accuracy: 1
time_ms: 240
memory_kb: 38084
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <map>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}

double solve(int k, VP v){
    int n = v.size();
    P diff = v[k];
    for(int i=0; i<n; i++){
        v[i] -= diff;
    }
    double rot = arg(v[(k+1)%n] -v[k]);
    for(int i=0; i<n; i++){
        v[i] = rotate(v[i], -rot);
    }
    double xmin=INF,xmax=-INF,ymin=INF,ymax=-INF;
    for(int i=0; i<n; i++){
        xmin = min(xmin, v[i].X);
        xmax = max(xmax, v[i].X);
        ymin = min(ymin, v[i].Y);
        ymax = max(ymax, v[i].Y);
    }
    return (xmax-xmin)*(ymax-ymin);
}

int main(){
    int n;
    cin >> n;
    VP dir{P(-1,0), P(0,-1), P(1,0), P(0,1)};
    VP v(n);
    v[0] = P(0, 0);
    for(int i=1; i<n; i++){
        int idx,d;
        cin >> idx >> d;
        v[i] = v[idx]+dir[d];
    }
    VP p(4*n);
    VP vdir{P(0,0), P(0,1), P(1,0), P(1,1)};
    for(int i=0; i<n; i++){
        for(int d=0; d<4; d++){
            p[4*i+d] = v[i]+vdir[d];
        }
    }
    p = convex(p);

    double ans = INF;
    for(int i=0; i<(int)p.size(); i++){
        ans = min(ans, solve(i, p));
    }
    cout << fixed << setprecision(10);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 16844
final_rank: 2

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()
typedef complex<double> P;
typedef vector<P> VP;

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

VP convex(VP v){
    VP ret;
    int n = v.size();
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++){
        while((int)ret.size()>1 && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    int t = ret.size();
    for(int i=n-2; i>=0; i--){
        while((int)ret.size()>t && cross(ret.back()-ret[ret.size()-2], v[i]-ret.back()) < EPS){
            ret.pop_back();
        }
        ret.push_back(v[i]);
    }
    if((int)ret.size() > 1) ret.pop_back();
    return ret;
}

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};
int ddx[4] = {0, 0, 1, 1};
int ddy[4] = {0, 1, 0, 1};

int main(){
    int n;
    cin >> n;

    VP tile(n);
    tile[0] = P(0, 0);
    for(int i=1; i<n; i++){
        int n,d;
        cin >> n >> d;
        tile[i] = tile[n] +P(dx[d], dy[d]);
    }
    VP points(4*n);
    for(int i=0; i<n; i++){
        for(int j=0; j<4; j++){
            points[4*i +j] = tile[i] +P(ddx[j], ddy[j]);
        }
    }
    points = convex(points);

    int m = points.size();
    double ans = INF;
    for(int i=0; i<m; i++){
        double angle = -arg(points[(i+1)%m] -points[i]);
        P rot(cos(angle), sin(angle));
        double xmin=INF, xmax=-INF, ymin=INF, ymax=-INF; 
        for(P p: points){
            p *= rot;
            xmin = min(xmin, p.X);
            xmax = max(xmax, p.X);
            ymin = min(ymin, p.Y);
            ymax = max(ymax, p.Y);
        }
        ans = min(ans, (xmax -xmin) *(ymax -ymin));
    }
    cout << fixed << setprecision(10);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 16848
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define inf 1<<29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ 
    return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ 
    return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

double getDistance(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

Polygon convex_hull(Polygon s){
  Polygon g;
  int n=s.size();
  if(n<3)return s;

  sort(s.begin(),s.end());

  for(int i=0;i<n;i++){
    for(int n=g.size();n>=2&&ccw(g[n-2],g[n-1],s[i])==1;n--){
      g.pop_back();
    }
    g.push_back(s[i]);
  }
  for(int i=n-2;i>=0;i--){
    for(int n=g.size();n>=2&&ccw(g[n-2],g[n-1],s[i])==1;n--){
      g.pop_back();
    }
    g.push_back(s[i]);
  }
  reverse(g.begin(),g.end());
  g.pop_back();
  return g;
}

double solve(Polygon p){
  double ans = linf;
  sort(all(p));
  Unique(p);
  Polygon P = convex_hull(p);
  FOR(i,0,P.size()){
    Line L(P[i],P[(i+1)%P.size()]);
    double h=0,w1=0,w2=0;
    FOR(j,0,P.size()){
      h = max(h,getDistance(L,P[j]));
      Point c=project(L,P[j]);
      if(ccw(L.p1,L.p2,c)==2)w1=max(w1,abs(L.p1-c));
      else w2=max(w2,abs(L.p1-c));
    }
    ans = min(ans,h*(w1+w2));
  }
  return ans;
}

int main()
{
  int N,n,d;
  cin>>N;
  Polygon p(N);
  p[0]=Point(0,0);
  FOR(i,1,N){
    cin>>n>>d;
    if(d==0)p[i]=Point(p[n].x-1,p[n].y);
    else if(d==1)p[i]=Point(p[n].x,p[n].y-1);
    else if(d==2)p[i]=Point(p[n].x+1,p[n].y);
    else p[i]=Point(p[n].x,p[n].y+1);
  }
  FOR(i,0,N){
    p.pb(Point(p[i].x+1,p[i].y));
    p.pb(Point(p[i].x,p[i].y+1));
    p.pb(Point(p[i].x+1,p[i].y+1));
  }
  pd(solve(p));
  return 0;
}
accuracy: 0.6363636363636364
time_ms: 70
memory_kb: 16872
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define F first
#define S second
const double EPS = 1e-10;
const double INF = 1e12;
typedef complex<double> P;
typedef pair<P,P> L;
namespace std {
  bool operator < (const P& a, const P& b) {
    return real(a)!=real(b)?real(a)<real(b):imag(a)<imag(b);
  }
}
bool cmp(P a,P b) {return atan2(a.imag(),a.real())<atan2(b.imag(),b.real());}
double cross(const P& a, const P& b) {return imag(conj(a)*b);}
double dot(const P& a, const P& b) {return real(conj(a)*b);}
int ccw(P a, P b, P c) {
  b-=a;c-=a;
  if(cross(b,c)>EPS)return +1;
  if(cross(b,c)<-EPS)return -1;
  if(dot(b,c)<-EPS)return +2;
  if(norm(b)<norm(c))return -2;
  return 0;
}
double D(P a, P b) {
  return sqrt((a.real()-b.real())*(a.real()-b.real())+(a.imag()-b.imag())*(a.imag()-b.imag()));
}
P rotate(P a, double r) {
  return P(a.real()*cos(r)-a.imag()*sin(r),a.real()*sin(r)+a.imag()*cos(r));
}
P projection(const L &l, const P &p) {
  double t = dot(p-l.F, l.F-l.S) / norm(l.F-l.S);
  return l.F + t*(l.F-l.S);
}
double toRad(double agl) {return agl*M_PI/180.0;}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
vector<P> convex_hull(vector<P> p) {
  int n = p.size(), k = 0;
  sort(p.begin(), p.end());
  vector<P> q(2*n);
  for(int i = 0; i < n; q[k++] = p[i++])
    while(k >= 2 && ccw(q[k-2], q[k-1], p[i]) <= 0) --k;
  for(int i = n-2, t = k+1; i >= 0; q[k++] = p[i--])
    while(k >= t && ccw(q[k-2], q[k-1], p[i]) <= 0) --k;
  q.resize(k-1);
  return q;
}

int main() {
  int n;
  cin >> n;
  vector<P> a;
  a.push_back(P(0,0));
  for(int i=0; i<n-1; i++) {
    int x,y;
    cin >> x >> y;
    P p=a[x],q;
    if(y==0) q=P(p.real()-1,p.imag());
    if(y==1) q=P(p.real(),p.imag()-1);
    if(y==2) q=P(p.real()+1,p.imag());
    if(y==3) q=P(p.real(),p.imag()+1);
    a.push_back(q);
  }
  vector<P> v;
  for(int i=0; i<n; i++) {
    for(int j=0; j<2; j++) {
      for(int k=0; k<2; k++) v.push_back(P(a[i].real()+j,a[i].imag()+k));
    }
  }
  sort(v.begin(),v.end());
  v.erase(unique(v.begin(),v.end()),v.end());
  v=convex_hull(v);
  n=v.size();
  double ans=INF;
  for(int i=0; i<n; i++) {
    rotate(v.begin(),v.begin()+1,v.end());
    P q=rotate(v[1]-v[0],toRad(90+EPS))+v[0];
    L s=L(v[0],v[1]);
    L t=L(v[0],q);
    int l=2,r=n;
    while(l+1<r) {
      int m=(l+r)/2;
      if(ccw(q,v[0],v[m])<0) r=m;
      else l=m;
    }
    int k=l;
    l=2,r=k;
    for(int j=0; j<1000; j++) {
      int m1=(l*2+r)/3,m2=(l+r*2)/3;
      double d1=distanceLP(t,v[m1]),d2=distanceLP(t,v[m2]);
      if(d1<d2) l=m1;
      else r=m2;
    }
    l=(l+r)/2;
    double xx=distanceLP(t,v[l]);
    if(abs(ccw(q,v[0],v[k]))==1) k++;
    l=k,r=n;
    for(int j=0; j<1000; j++) {
      int m1=(l*2+r)/3,m2=(l+r*2)/3;
      double d1=distanceLP(t,v[m1]),d2=distanceLP(t,v[m2]);
      if(d1<d2) l=m1;
      else r=m2;
    }
    l=(l+r)/2;
    xx+=distanceLP(t,v[l]);
    l=2,r=n;
    for(int j=0; j<1000; j++) {
      int m1=(l*2+r)/3,m2=(l+r*2)/3;
      double d1=distanceLP(s,v[m1]),d2=distanceLP(s,v[m2]);
      if(d1<d2) l=m1;
      else r=m2;
    }
    l=(l+r)/2;
    double yy=distanceLP(s,v[l]);
    ans=min(ans,xx*yy);
  }
  printf("%.10f\n",ans);
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 20112
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repl(i,0,n)
#define mp(a,b) make_pair((a),(b))
#define pb(a) push_back((a))
#define all(x) (x).begin(),(x).end()
#define uniq(x) sort(all(x)),(x).erase(unique(all(x)),end(x))
#define fi first
#define se second
#define dbg(...) _dbg(#__VA_ARGS__",", __VA_ARGS__)
void _dbg(string){cout<<endl;}
template<class H,class... T> void _dbg(string s,H h,T... t){int l=s.find(',');cout<<s.substr(0,l)<<" = "<<h<<", ";_dbg(s.substr(l+1),t...);}
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

#define INF 1120000000
#define EPS 1e-8

// ???????°???°???????????????
inline double add(double a, double b){
  if(abs(a+b) < EPS*(abs(a) + abs(b))) return 0;
  return a+b;
}

struct Point{
  double x,y;
  Point() {}
  Point(double nx, double ny) : x(nx), y(ny) {}
  inline Point operator + (const Point p){ return Point(add(x, p.x), add(y, p.y)); }
  inline Point operator - (const Point p){ return Point(add(x,-p.x), add(y,-p.y)); }
  inline Point operator * (double d){ return Point(x*d, y*d); }
  inline double dot(const Point p){ return add(x * p.x, y*p.y); }  //??????
  inline double det(const Point p){ return add(x * p.y, -y*p.x); } //??????
  inline double dist(const Point p){ return sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y)); }
  inline bool operator < (const Point p) const {
    if(x != p.x) return x < p.x;
    else return y < p.y;
  }
  inline bool operator == (const Point p) const {
    return (add(x, -p.x)==0) && (add(y, -p.y)==0);
  }
  friend ostream& operator<<(ostream& os, const Point& p) {
    os << "[" << p.x << "," << p.y << "]";
    return os;
  }
};

double norm(Point p) {return p.x*p.x+p.y*p.y;}
Point proj(Point a1, Point a2, Point p){
  return a1+(a2-a1) * ( (a2-a1).dot(p-a1)/norm(a2-a1) );
}

vector<Point> GrahamScan(vector<Point> points){
  int n = points.size();
  sort(all(points));
  int k=0;
  vector<Point> qs(2*n);
  for(int i=0; i<n; qs[k++] = points[i++]){
    while(k>1 && (qs[k-1] - qs[k-2]).det(points[i] - qs[k-1]) <= 0) k--;
  }
  for(int i=n-2,t=k; i>=0; qs[k++] = points[i--]){
    while(k>t && (qs[k-1] -qs[k-2]).det(points[i] - qs[k-1]) <= 0) k--;
  }
  qs.resize(k-1);
  return qs;
}

int main(){
  int n;
  cin>>n;
  const int dx[] = {-1,0,1,0}, dy[]={0,-1,0,1};
  vector<Point> vec;
  rep(x,2)rep(y,2) vec.pb(Point(x,y));
  rep(i,n-1){
    int p,d;
    cin>>p>>d;
    double bx = vec[p*4].x+dx[d], by = vec[p*4].y+dy[d];
    rep(x,2)rep(y,2) vec.pb(Point(bx+x, by+y));
  }

  vec = GrahamScan(vec);
  n = vec.size();

  int i=0,j=0,k=0,l=0;
  while(vec[i].y>vec[i+1].y) i = (i+1)%n;
  j = i;
  while(vec[j].x<vec[j+1].x) j = (j+1)%n;
  k = j;
  while(vec[k].y<vec[k+1].y) k = (k+1)%n;
  l = k;
  while(vec[l].x>vec[l+1].x) l = (l+1)%n;

  auto area = [&](int a, int b, int c, int d){
    Point p1 = proj(vec[a], vec[(a+1)%n], vec[b]);
    Point p2 = proj(vec[a], vec[(a+1)%n], vec[d]);
    double w = p1.dist(p2);
    Point p3 = proj(vec[a], vec[(a+1)%n], vec[c]);
    double h = vec[c].dist(p3);
//    dbg(a,b,c,d,vec, w*h);
    return w*h;
  };
//dbg(vec);
  double best = area(i,j,k,l);
  int si=i;
  int cnt = 0;
  while(si != i || cnt<n){
    i = (i+1)%n;
    if(i==j) j = (j+1)%n;

    while( (vec[(i+1)%n]-vec[i]).det(vec[(k+1)%n]-vec[k]) >= 0){
      k = (k+1)%n;
      if(k==l) l= (l+1)%n;
    }

    while( (vec[(i+1)%n]-vec[i]).dot(vec[j] - vec[(j-1+n)%n]) * (vec[(i+1)%n]-vec[i]).dot(vec[(j+1)%n] - vec[j]) > 0 ) j = (j+1)%n;
    while( (vec[(i+1)%n]-vec[i]).dot(vec[l] - vec[(l-1+n)%n]) * (vec[(i+1)%n]-vec[i]).dot(vec[(l+1)%n] - vec[l]) > 0 ) l =  (l+1)%n;

    best = min(best, area(i,j,k,l));
    cnt++;
  }

  printf("%.7f\n", best);

  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 15372
final_rank: 1

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a)  (a).begin(),(a).end()
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define pb push_back
 
 
const double INF = (1E20);
#define EPS (1e-10)
class P{
public:
    double x,y;
     
    P(double _x=0,double _y=0):x(_x),y(_y){};
    P operator - (const P &p ) const { return P(x-p.x,y-p.y);}
};
 
struct S{P p1,p2;};
 
 
typedef vector<P> Polygon;
typedef P Vector;
 
double abs(P p)                 {return sqrt(p.x*p.x + p.y*p.y);}
double dot(Vector a, Vector b)  {return a.x*b.x+a.y*b.y;}
 
     
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
 
bool cmp_x(const P& p,const P& q){
    if(p.x!=q.x)return p.x<q.x;
    return p.y<q.y;
}
 
vector<P> convex_hull(vector<P> ps){
    int n = ps.size();
    sort(all(ps),cmp_x);
    int k=0;
    vector<P> qs(n*2);
    rep(i,n){
        while(k>1 && cross((qs[k-1]-qs[k-2]),(ps[i]-qs[k-1]))<=0)k--;
         
        qs[k++] = ps[i];
    }
    for(int i=n-2,t=k;i>=0;i--){
        while(k>t && cross((qs[k-1]-qs[k-2]),(ps[i]-qs[k-1]))<=0 )k--;
        qs[k++]=ps[i];
    }
    qs.resize(k-1);
    return qs;
}
 
 
int px[1000005];
int py[1000005];
 
double getLR(S edge,vector<P> &tpol){
    double l=INF,r=-INF;
     
    rep(i,tpol.size()){
        P cur = tpol[i];
        Vector a,b;
        a = edge.p2 - edge.p1;
        b = cur - edge.p1;
        double tt = dot(a,b);
        tt /= abs(a);
       // cout<< tt <<endl;
        l=min(l,tt);
        r=max(r,tt);
    }
  //  cout<<endl;
    return r-l;
}
 
double getU(S edge,vector<P> &tpol){
    double res=-INF;
     
    rep(i,tpol.size()){
        P cur = tpol[i];
        Vector a,b;
        a = edge.p2 - edge.p1;
        b = cur - edge.p1;
        double tt = cross(a,b);
        tt /= abs(a);
         
        res=max(res, abs(tt ));
    }
    return res;
}
 
int main(){
    int n;
    cin>>n;
     
     
    vector<P> points;
    px[0]=py[0]=0;
     
    for(int i=1;i<n;i++){
        int id,dir;
        cin>>id>>dir;
        if(dir==0){
            px[i]=px[id]-1;
            py[i]=py[id];
        }else if(dir==1){
            px[i]=px[id];
            py[i]=py[id]-1;
        }else if(dir==2){
            px[i]=px[id]+1;
            py[i]=py[id];
        }else if(dir==3){
            px[i]=px[id];
            py[i]=py[id]+1;
        }
    }
    set< pair<int,int> > st;
    for(int i=0;i<n;i++){
        for(int dy=0;dy<2;dy++)
            for(int dx=0;dx<2;dx++)
                st.insert( make_pair( px[i]+dx ,py[i]+dy) );
         
    }
     
    for( pair<int,int> sp : st ){
         
        //cout<< sp.first << ' ' <<sp.second <<endl;
         
        points.emplace_back( sp.first , sp.second );
    }
     
    vector<P> tpol = convex_hull(points);
     
    double ans=INF;
     
    rep(i,tpol.size()){
        S edge = S{tpol[i],tpol[(i+1)%tpol.size()]};
         
        double width = getLR(edge,tpol);
        double height = getU(edge,tpol);
         
//        cout<<edge.p1.x<<" "<<edge.p1.y<<" "<<edge.p2.x<<" "<<edge.p2.y<<endl;
//        cout<<width<<" "<<height<<endl;
         
        ans=min(ans, width * height );
    }
    printf("%.10f\n",ans);
     
}
accuracy: 1
time_ms: 110
memory_kb: 25604
final_rank: 11

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define EPS (1e-10)
 
struct Point {
    double x, y;
 
    Point() {}
    Point (double x, double y) : x(x), y(y) {}
 
    Point operator + (const Point &p) const {
        return Point(x + p.x, y + p.y);
    }
     
    Point operator - (const Point &p) const {
        return Point(x - p.x, y - p.y);
    }
     
    Point operator * (const double &k) const {
        return Point(x * k, y * k);
    }
 
    bool operator < (const Point &p) const {
        return x != p.x ? x < p.x : y < p.y;
    }
 
    bool operator == (const Point &p) const {  return (x == p.x && y == p.y); }
};
 
double dot(const Point &a, const Point &b)
{
    return a.x * b.x + a.y * b.y;
}
 
double cross(const Point &a, const Point &b)
{
    return a.x * b.y - b.x * a.y;
}
 
double norm(const Point &p)
{
    return dot(p, p);
}
 
double abs(const Point &p)
{
    return sqrt(norm(p));
}
 
double dist(const Point &a, const Point &b)
{
    return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
 
#define COUNTER_CLOCKWISE +1
#define CLOCKWISE         -1
#define ONLINE_BACK       +2
#define ONLINE_FRONT      -2
#define ON_SEGMENT        +0
typedef Point Vector;
 
int ccw(const Point &p0, const Point &p1, const Point &p2)
{
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if (cross(a, b) > EPS)  return COUNTER_CLOCKWISE;
    if (cross(a, b) < -EPS) return CLOCKWISE;
    if (dot(a, b) < -EPS)   return ONLINE_BACK;
    if (norm(a) < norm(b))  return ONLINE_FRONT;
    return ON_SEGMENT;
}
 
bool sortY(Point p1, Point p2)
{
    if (p1.y != p2.y) {
    return (p1.y - p2.y < -EPS);
    } else { 
    return (p1.x - p2.x < -EPS);
    }
}
 
typedef vector<Point> Polygon;
 
Polygon convex_hull(Polygon &ps)
{
    int N = ps.size(), j = 0;
    Polygon pg(N * 2);
    sort(ps.begin(), ps.end(), sortY);
    for (int i = 0; i < N; i++) {
    while (j > 1 && cross(pg[j - 1] - pg[j - 2], ps[i] - pg[j - 1]) <= 0) {
        j--;
    }
    pg[j++] = ps[i];
    }
    int k = j;
    for (int i = N - 2; i >= 0; i--) {
    while (j > k && cross(pg[j - 1] - pg[j - 2], ps[i] - pg[j - 1]) <= 0) {
        j--;
    }
    pg[j++] = ps[i];
    }
    pg.resize(j - 1);
    return pg;
}
 
void insert(set<Point> &points, Point p)
{
    const int dx[] = {-1, -1, +1, +1};
    const int dy[] = {-1, +1, +1, -1};
 
    for (int i = 0; i < 4; i++) {
        double nx = p.x + dx[i] / 2.0;
        double ny = p.y + dy[i] / 2.0;
        points.insert(Point(nx, ny));
    }   
}
 
struct Segment {
    Point s, t;
    Segment () {}
    Segment (Point s, Point t) : s(s), t(t) {}
};
 
typedef Segment Line;
 
Point projection(const Segment &s, const Point &p)
{
    Vector b = s.t - s.s;
    double t = dot(p - s.s, b) / norm(b);
    return s.s + b * t;
}
 
double distanceLP(const Line &l, const Point &p)
{
    return abs(p - projection(l, p));
}
 
int main()
{
    int N;
    cin >> N;
     
    set<Point> points;
    insert(points, Point(0, 0));
     
    vector<Point> p(N);
    p[0] = Point(0, 0);
 
    const int dx[] = {-1, +0, +1, +0};
    const int dy[] = {+0, +1, +0, -1};
     
    for (int i = 0; i < N - 1; i++) {
        int n, d;
        cin >> n >> d;
        p[i + 1] = Point(p[n].x + dx[d], p[n].y + dy[d]);
        insert(points, p[i + 1]);
    }
     
    Polygon pg;
    for (auto &point: points) {
        pg.push_back(point);
    }
    pg = convex_hull(pg);
    N = pg.size();
    double res = 1e55;    
    for (int i = 0; i < N; i++) {
        int ci = i, ni = (i + 1) % N;
        Line l1(pg[ci], pg[ni]);
         
        int jj = -1;
        double h = 0;
        for (int j = 0; j < N; j++) {
            double d = distanceLP(l1, pg[j]);
            if (d > h) {
                h = d;
                jj = j;
            }
        }
        Point pp = projection(l1, pg[jj]);               
        Line l2(pp, pg[jj]);
 
        if (pp == pg[jj]) continue;
         
        jj = -1;
        double w1 = 0;
        for (int j = 0; j < N; j++) {
            double d = distanceLP(l2, pg[j]);
            if (d > w1) {
                w1 = d;
                jj = j;
            }
        }
        Point pp2 = projection(l1, pg[jj]);
        Line l3(pp2, pg[jj]);
 
        if (pp2 == pg[jj]) continue;
         
        double w = 0;        
        for (int j = 0; j < N; j++) {
            double d = distanceLP(l3, pg[j]);
            if (d > w) w = d;
        }        
        res = min(res, h * w);
    }
    printf("%.10f\n", res);
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 21088
final_rank: 10

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define all(a)  (a).begin(),(a).end()
#define pb push_back
#define INF (1e10+1)
//#define INF (1LL<<59)
 
 
#define OUT 0
#define ON 1
#define IN 2
#define EPS (1e-10)
class P{                    //???
public:
    double x,y;
     
    P(double _x=0,double _y=0):x(_x),y(_y){};
    P operator + (const P &p     )const{ return P( x+p.x , y+p.y ); }  //??????
    P operator - (const P &p     )const{ return P( x-p.x , y-p.y ); }  //??????
    P operator * (const double k )const{ return P( x*k   , y*k    ); } //??????
    P operator / (const double k )const{ return P( x/k   , y/k    ); } //??????
     
    bool operator == (const P &p){ return ( fabs(x-p.x)<EPS && fabs(y-p.y)<EPS ); }
    bool operator < (const P &p) const{ return ( x!=p.x ? x<p.x:y<p.y ); }
     
    double norm(){ return x*x+y*y; }        //?????????
    double abs() { return sqrt(norm()); }   //???§??????
    void normalize() {double d = sqrt(x*x+y*y); x /= d; y /= d;}    //???£??????
};
struct C{P p;double r;};    //???
struct S{P p1,p2;};         //??????
typedef vector<P> Polygon;  //?????§????¢
typedef P Vector;           //????????????
typedef S L;                //???´???
 
double norm (P p)               { return p.norm(); }
double abs  (P p)               { return p.abs(); }
double dot  (Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
double cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; }
double sqDist(P a, P b)         {return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
double dist (P a, P b)          {return sqrt(sqDist(a,b));}
Vector vec(S a)                 {return P(a.p2.x-a.p1.x,a.p2.y-a.p1.y);}
 
 
//?????? verified AOJ0068,QUPC-G
//????????????§??????
bool cmp_x(const P& p, const P& q){
    if(p.x != q.x)return p.x<q.x;
    return p.y<q.y;
}
 
//???????????±???????
vector<P> convex_hull(vector<P> ps){
    int n = ps.size();
    sort(all(ps),cmp_x);
    int k=0;            //??????????????????°
    vector<P> qs(n*2);  //??§????????????????
    //??????´???????????????
    rep(i,n){
        while( k>1 && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
        qs[k++]=ps[i];
    }
    //??????´???????????????
    for(int i=n-2, t=k;i>=0;i--){
        while( k>t && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
        qs[k++]=ps[i];
    }
    qs.resize(k-1);
    return qs;
}
 
 
 
double solveLR(vector<P> ps,S l){
    double mini=INF;
    double maxi=-INF;
     
    rep(i,ps.size()){
        double res = dot(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
        mini = min(res,mini);
        maxi = max(res,maxi);
    }
    return maxi-mini;
}
 
double solveU(vector<P> ps,S l){
    double maxi = -INF;
    rep(i,ps.size()){
        double res = cross(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
        maxi = max(maxi,abs(res));
    }
    return maxi;
}
 
 
int main(){
    int n;
    cin>>n;
     
    vector<P> inp(n);
    inp[0] = P(0,0);
    for(int i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        if(b==0)        inp[i] = inp[a]+P(-1,0);
        else if(b==1)   inp[i] = inp[a]+P(0,-1);
        else if(b==2)   inp[i] = inp[a]+P(+1,0);
        else if(b==3)   inp[i] = inp[a]+P(0,+1);
    }
    set<P> ps;
    rep(i,n){
        ps.insert(inp[i]+P(0,0));
        ps.insert(inp[i]+P(1,0));
        ps.insert(inp[i]+P(0,1));
        ps.insert(inp[i]+P(1,1));
    }
     
    vector<P> arg;
    for(auto &elm:ps)arg.pb(elm);
     
    vector<P> points = convex_hull(arg);
     
    double ans = INF;
     
    rep(i,points.size()){
        S line = S{points[i],points[(i+1)%points.size()]};
         
        double LR = solveLR(points,line);
        double U  = solveU(points,line);
//      cout<<LR<<" "<<U<<endl;
        ans = min( ans , LR*U );
    }
    printf("%.10lf\n",ans);
}
accuracy: 1
time_ms: 140
memory_kb: 29500
final_rank: 12

code_snippet: #include<bits/stdc++.h>
 
using namespace std;
 
#define eps 1e-8
 
struct Point
{
  double x, y;
 
  Point(double a = 0, double b = 0) :
    x(a), y(b)
  {
  }
 
  bool operator<(const Point& a) const
  {
    if(fabs(x - a.x) > eps) return x < a.x;
    return y < a.y;
  }
 
  bool operator==(const Point& a) const
  {
    return fabs(x - a.x) < eps && fabs(y - a.y) < eps;
  }
 
  Point operator+(const Point& a) const
  {
    return Point(x + a.x, y + a.y);
  }
 
  Point operator-(const Point& a) const
  {
    return Point(x - a.x, y - a.y);
  }
 
  Point operator/(const double val) const
  {
    return Point(x / val, y / val);
  }
 
  Point operator*(const double val) const
  {
    return Point(x * val, y * val);
  }
};
 
typedef Point Vector;
 
double dist(Point a, Point b)
{
  return hypot(a.x - b.x, a.y - b.y);
}
 
double dot(Point a, Point b)
{
  return a.x * b.x + a.y * b.y;
}
 
double cross2(Point a, Point b)
{
  return a.x * b.y - a.y * b.x;
}
 
double cross(Point o, Point a, Point b)
{
  return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}
 
int between(Point a, Point b, Point c)
{
  return dot(c - a, b - a) >= 0 && dot(c - b, a - b) >= 0;
}
 
int onSeg(Point a, Point b, Point c)
{
  return between(a, b, c) && fabs(cross(a, b, c)) < eps;
}
 
double distProjection(Point as, Point at, Point s)
{
  double a, b, c;
  a = at.y - as.y;
  b = as.x - at.x;
  c = -(a * as.x + b * as.y);
  return fabs(a * s.x + b * s.y + c) / hypot(a, b);
}
 
struct Seg
{
  Point s, e;
};
 
int calcIntersection(Seg a, Seg b, Point& p)
{
  double a1, b1, c1, a2, b2, c2;
  double d, dx, dy;
  a1 = a.s.y - a.e.y, b1 = -a.s.x + a.e.x;
  a2 = b.s.y - b.e.y, b2 = -b.s.x + b.e.x;
  c1 = a1 * a.s.x + b1 * a.s.y;
  c2 = a2 * b.s.x + b2 * b.s.y;
  d = a1 * b2 - a2 * b1;
  dx = c1 * b2 - c2 * b1;
  dy = a1 * c2 - a2 * c1;
  if(fabs(d) < eps) // NONE or LINE
    return 0;
  p.x = dx / d, p.y = dy / d;
  return onSeg(a.s, a.e, p) && onSeg(b.s, b.e, p);
}
 
int inPolygon(Point p[], int n, Point q)
{
  int i, j, cnt = 0;
  for(i = 0, j = n - 1; i < n; j = i++) {
    if(p[i].y > q.y != p[j].y > q.y &&
       q.x < (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y) + p[i].x)
      cnt++;
  }
  return cnt & 1;
}
 
double calcArea(Point p[], int n)
{
  if(n < 3) return 0.0;
  double ret = 0;
  int i;
  p[n] = p[0];
  for(i = 0; i < n; i++)
    ret += p[i].x * p[i + 1].y - p[i].y * p[i + 1].x;
  return fabs(ret) / 2;
}
 
int monotone(int n, Point p[], Point ch[])
{
  sort(p, p + n);
  int i, m = 0, t;
  for(i = 0; i < n; i++) {
    while(m >= 2 && cross(ch[m - 2], ch[m - 1], p[i]) <= 0)
      m--;
    ch[m++] = p[i];
  }
  for(i = n - 1, t = m + 1; i >= 0; i--) {
    while(m >= t && cross(ch[m - 2], ch[m - 1], p[i]) <= 0)
      m--;
    ch[m++] = p[i];
  }
  return m - 1;
}
 
#define INF 1e+30
 
double smallRect(int n, Point ch[])
{
  double lx, ly, rx, ry;
  int up, down, left, right;
  double ret = INF;
  lx = ly = INF;
  rx = ry = -INF;
 
  up = down = left = right = 0;
  for(int i = 0; i < n; i++) {
    if(ch[i].x > rx) rx = ch[i].x, right = i;
    if(ch[i].y > ry) ry = ch[i].y, up = i;
    if(ch[i].x < lx) lx = ch[i].x, left = i;
    if(ch[i].y < ly) ly = ch[i].y, down = i;
  }
 
  int corner[] = {up, down, left, right};
  Point vec[] = {Point(-1, 0), Point(1, 0), Point(0, -1), Point(0, 1)};
 
  ret = (rx - lx) * (ry - ly);
  for(int j = 0; j < 4; j++) {
    while(true) {
      Point a = ch[corner[j]], b = ch[(corner[j] + 1) % n], c = vec[j];
      if(fabs(cross2(b - a, c)) < eps)
        corner[j] = (corner[j] + 1) % n;
      else
        break;
    }
  }
  for(int i = 0; i < n; i++) {
    double mxVal = -INF, cos, sin;
    int mxIdx = 0;
    for(int j = 0; j < 4; j++) {
      Point a = ch[corner[j]], b = ch[(corner[j] + 1) % n], c = vec[j];
      double cosA = dot(b - a, c) / dist(b, a) / dist(c, Point(0, 0));
      if(mxVal < cosA)
        mxVal = cosA, mxIdx = j;
    }
    cos = mxVal, sin = sqrt(1 - cos * cos);
    for(int j = 0; j < 4; j++) {
      double tx, ty;
      tx = vec[j].x * cos - vec[j].y * sin;
      ty = vec[j].x * sin + vec[j].y * cos;
      vec[j] = Point(tx, ty);
    }
    for(int j = 0; j < 4; j++) {
      while(true) {
        Point a = ch[corner[j]], b = ch[(corner[j] + 1) % n], c = vec[j];
        if(fabs(cross2(b - a, c)) < eps)
          corner[j] = (corner[j] + 1) % n;
        else
          break;
      }
    }
    double w = distProjection(ch[corner[0]], ch[corner[0]] + vec[0], ch[corner[1]]);
    double h = distProjection(ch[corner[2]], ch[corner[2]] + vec[2], ch[corner[3]]);
    ret = min(ret, w * h);
  }
  return ret;
}
 
 
int xx[100001], yy[100001];
vector< Point > pp;
Point ch[400007], k[400007];
 
int main()
{
  int N;
  cin >> N;
  int vy[] = {0, 1, 0, -1}, vx[] = {1, 0, -1, 0};
  xx[0] = 0, yy[0] = 0;
  pp.push_back((Point) {0.0, 0.0});
  pp.push_back((Point) {1.0, 0.0});
  pp.push_back((Point) {0.0, 1.0});
  pp.push_back((Point) {1.0, 1.0});
 
  int tail = 0;
  for(int i = 1; i < N; i++) {
    int n, d;
    cin >> n >> d;
    double x = xx[n] + vx[d];
    double y = yy[n] + vy[d];
    xx[i] = x, yy[i] = y;
 
    pp.push_back((Point) {x, y});
    pp.push_back((Point) {x + 1, y});
    pp.push_back((Point) {x, y + 1});
    pp.push_back((Point) {x + 1, y + 1});
  }
  for(int i = 0; i < pp.size(); i++) {
    k[i] = pp[i];
  }
  int m = monotone(pp.size(), k, ch);
  double ret = smallRect(m, ch);
  printf("%.8lf\n", ret);
}
accuracy: 1
time_ms: 70
memory_kb: 24216
final_rank: 8

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define all(a)  (a).begin(),(a).end()
#define pb push_back
#define INF (1e10+1)
//#define INF (1LL<<59)


#define OUT 0
#define ON 1
#define IN 2
#define EPS (1e-10)
class P{                    //???
public:
	double x,y;
	
	P(double _x=0,double _y=0):x(_x),y(_y){};
	P operator + (const P &p     )const{ return P( x+p.x , y+p.y ); }  //??????
	P operator - (const P &p     )const{ return P( x-p.x , y-p.y ); }  //??????
	P operator * (const double k )const{ return P( x*k   , y*k    ); } //??????
	P operator / (const double k )const{ return P( x/k   , y/k    ); } //??????
	
	bool operator == (const P &p){ return ( fabs(x-p.x)<EPS && fabs(y-p.y)<EPS ); }
	bool operator < (const P &p) const{ return ( x!=p.x ? x<p.x:y<p.y ); }
	
	double norm(){ return x*x+y*y; }        //?????????
	double abs() { return sqrt(norm()); }   //??§??????
	void normalize() {double d = sqrt(x*x+y*y); x /= d; y /= d;}	//??£??????
};
struct C{P p;double r;};    //???
struct S{P p1,p2;};         //??????
typedef vector<P> Polygon;  //????§???¢
typedef P Vector;           //????????????
typedef S L;                //??´???

double norm (P p)               { return p.norm(); }
double abs  (P p)               { return p.abs(); }
double dot  (Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
double cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; }
double sqDist(P a, P b)         {return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
double dist (P a, P b)          {return sqrt(sqDist(a,b));}
Vector vec(S a)                 {return P(a.p2.x-a.p1.x,a.p2.y-a.p1.y);}


//?????? verified AOJ0068,QUPC-G
//???????????§??????
bool cmp_x(const P& p, const P& q){
	if(p.x != q.x)return p.x<q.x;
	return p.y<q.y;
}

//??????????±???????
vector<P> convex_hull(vector<P> ps){
	int n = ps.size();
	sort(all(ps),cmp_x);
	int k=0;            //?????????????????°
	vector<P> qs(n*2);  //?§????????????????
	//?????´???????????????
	rep(i,n){
		while( k>1 && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
		qs[k++]=ps[i];
	}
	//?????´???????????????
	for(int i=n-2, t=k;i>=0;i--){
		while( k>t && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
		qs[k++]=ps[i];
	}
	qs.resize(k-1);
	return qs;
}



double solveLR(vector<P> ps,S l){
	double mini=INF;
	double maxi=-INF;
	
	rep(i,ps.size()){
		double res = dot(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
		mini = min(res,mini);
		maxi = max(res,maxi);
	}
	return maxi-mini;
}

double solveU(vector<P> ps,S l){
	double maxi = -INF;
	rep(i,ps.size()){
		double res = cross(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
		maxi = max(maxi,abs(res));
	}
	return maxi;
}


int main(){
	int n;
	cin>>n;
	
	vector<P> inp(n);
	inp[0] = P(0,0);
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		if(b==0)		inp[i] = inp[a]+P(-1,0);
		else if(b==1)	inp[i] = inp[a]+P(0,-1);
		else if(b==2)	inp[i] = inp[a]+P(+1,0);
		else if(b==3)	inp[i] = inp[a]+P(0,+1);
	}
	set<P> ps;
	rep(i,n){
		ps.insert(inp[i]+P(0,0));
		ps.insert(inp[i]+P(1,0));
		ps.insert(inp[i]+P(0,1));
		ps.insert(inp[i]+P(1,1));
	}
	
	vector<P> arg;
	for(auto &elm:ps)arg.pb(elm);
	
	vector<P> points = convex_hull(arg);
	
	double ans = INF;
	
	rep(i,points.size()){
		S line = S{points[i],points[(i+1)%points.size()]};
		
		double LR = solveLR(points,line);
		double U  = solveU(points,line);
//		cout<<LR<<" "<<U<<endl;
		ans = min( ans , LR*U );
	}
	printf("%.10lf\n",ans);
}
accuracy: 1
time_ms: 140
memory_kb: 29504
final_rank: 13

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define all(a)  (a).begin(),(a).end()
#define pb push_back
#define INF (1e9+1)
//#define INF (1LL<<59)


#define OUT 0
#define ON 1
#define IN 2
#define EPS (1e-10)
class P{                    //???
public:
	double x,y;
	
	P(double _x=0,double _y=0):x(_x),y(_y){};
	P operator + (const P &p     )const{ return P( x+p.x , y+p.y ); }  //??????
	P operator - (const P &p     )const{ return P( x-p.x , y-p.y ); }  //??????
	P operator * (const double k )const{ return P( x*k   , y*k    ); } //??????
	P operator / (const double k )const{ return P( x/k   , y/k    ); } //??????
	
	bool operator == (const P &p){ return ( fabs(x-p.x)<EPS && fabs(y-p.y)<EPS ); }
	bool operator < (const P &p) const{ return ( x!=p.x ? x<p.x:y<p.y ); }
	
	double norm(){ return x*x+y*y; }        //?????????
	double abs() { return sqrt(norm()); }   //??§??????
	void normalize() {double d = sqrt(x*x+y*y); x /= d; y /= d;}	//??£??????
};
struct C{P p;double r;};    //???
struct S{P p1,p2;};         //??????
typedef vector<P> Polygon;  //????§???¢
typedef P Vector;           //????????????
typedef S L;                //??´???

double norm (P p)               { return p.norm(); }
double abs  (P p)               { return p.abs(); }
double dot  (Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
double cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; }
double sqDist(P a, P b)         {return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
double dist (P a, P b)          {return sqrt(sqDist(a,b));}
Vector vec(S a)                 {return P(a.p2.x-a.p1.x,a.p2.y-a.p1.y);}


//?????? verified AOJ0068,QUPC-G
//???????????§??????
bool cmp_x(const P& p, const P& q){
	if(p.x != q.x)return p.x<q.x;
	return p.y<q.y;
}

//??????????±???????
vector<P> convex_hull(vector<P> ps){
	int n = ps.size();
	sort(all(ps),cmp_x);
	int k=0;            //?????????????????°
	vector<P> qs(n*2);  //?§????????????????
	//?????´???????????????
	rep(i,n){
		while( k>1 && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
		qs[k++]=ps[i];
	}
	//?????´???????????????
	for(int i=n-2, t=k;i>=0;i--){
		while( k>t && cross((qs[k-1]-qs[k-2]) , (ps[i]-qs[k-1]))<=0 ) k--;
		qs[k++]=ps[i];
	}
	qs.resize(k-1);
	return qs;
}



double solveLR(vector<P> ps,S l){
	double mini=INF;
	double maxi=-INF;
	
	rep(i,ps.size()){
		double res = dot(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
		mini = min(res,mini);
		maxi = max(res,maxi);
	}
	return maxi-mini;
}

double solveU(vector<P> ps,S l){
	double maxi = -INF;
	rep(i,ps.size()){
		double res = cross(l.p2-l.p1,ps[i]-l.p1)/abs(l.p2-l.p1);
		maxi = max(maxi,abs(res));
	}
	return maxi;
}


int main(){
	int n;
	cin>>n;
	
	vector<P> inp(n);
	inp[0] = P(0,0);
	for(int i=1;i<n;i++){
		int a,b;
		cin>>a>>b;
		if(b==0)		inp[i] = inp[a]+P(-1,0);
		else if(b==1)	inp[i] = inp[a]+P(0,-1);
		else if(b==2)	inp[i] = inp[a]+P(+1,0);
		else if(b==3)	inp[i] = inp[a]+P(0,+1);
	}
	set<P> ps;
	rep(i,n){
		ps.insert(inp[i]+P(0,0));
		ps.insert(inp[i]+P(1,0));
		ps.insert(inp[i]+P(0,1));
		ps.insert(inp[i]+P(1,1));
	}
	
	vector<P> arg;
	for(auto &elm:ps)arg.pb(elm);
	
	vector<P> points = convex_hull(arg);
	
	double ans = INF;
	
	rep(i,points.size()){
		S line = S{points[i],points[(i+1)%points.size()]};
		
		double LR = solveLR(points,line);
		double U  = solveU(points,line);
//		cout<<LR<<" "<<U<<endl;
		ans = min( ans , LR*U );
	}
	printf("%.10lf\n",ans);
}
accuracy: 0.7532467532467533
time_ms: 130
memory_kb: 29504
final_rank: 15