Problem:
Score : 700 points

Problem Statement

There are N bags, each containing two white balls. The i-th box contains two balls with integers x_i and y_i written on them, respectively.

For each of these bags, you will paint one of the balls red, and paint the other blue.

Afterwards, the 2N balls will be classified according to color.

Then, we will define the following:

R_{max}: the maximum integer written on a ball painted in red

R_{min}: the minimum integer written on a ball painted in red

B_{max}: the maximum integer written on a ball painted in blue

B_{min}: the minimum integer written on a ball painted in blue

Find the minimum possible value of (R_{max} - R_{min}) \times (B_{max} - B_{min}).

Constraints

1 ≤ N ≤ 200,000

1 ≤ x_i, y_i ≤ 10^9

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print the minimum possible value.

Sample Input 1

3
1 2
3 4
5 6

Sample Output 1

15

The optimal solution is to paint the balls with x_1, x_2, y_3 red, and paint the balls with y_1, y_2, x_3 blue.

Sample Input 2

3
1010 10
1000 1
20 1020

Sample Output 2

380

Sample Input 3

2
1 1
1000000000 1000000000

Sample Output 3

999999998000000001

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

/*
#pragma region GNUC
//https://yukicoder.me/wiki/auto_vectorization
#ifdef __GNUC__
#pragma GCC optimize ("O3")
#pragma GCC target ("avx")
#endif
#pragma endregion
*/
#define _USE_MATH_DEFINES
#pragma region include
#include <iostream>
#include <iomanip>
#include <stdio.h>

#include <sstream>
#include <algorithm>
#include <cmath>

#include <string>
#include <cstring>
#include <vector>
#include <tuple>

#include <queue>
#include <complex>
#include <set>
#include <map>
#include <stack>
#include <list>

#include <fstream>
#include <random>
//#include <time.h>
#include <ctime>
#pragma endregion //#include
/////////
#define REP(i, x, n) for(int i = x; i < n; ++i)
#define rep(i,n) REP(i,0,n)
/////////
#pragma region typedef
typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
#pragma endregion //typedef
////定数
const int INF = (int)1e9;
const LL MOD = (LL)1e9+7;
const LL LINF = (LL)1e18;
const double PI = acos(-1.0);
const double EPS = 1e-9;
/////////
using namespace::std;
/////////
#pragma region Math
#pragma region
template<class T>
inline T gcd(T a, T b){return b ? gcd(b, a % b) : a;}
#pragma endregion // 最大公約数 gcd
#pragma region
template<class T>
inline T lcm(T a, T b){return a / gcd(a, b) * b;}
#pragma endregion // 最小公倍数 lcm
#pragma region
LL powMod(LL num,LL n,LL mod=(LL)MOD){//(num**n)%mod
	num %= mod;//
	if( n == 0 ){
		return (LL)1;
	}
	LL mul = num;
	LL ans = (LL)1;
	while(n){
		if( n&1 ){
			ans = (ans*mul)%mod;
		}
		mul = (mul*mul)%mod;
		n >>= 1;
	}
	return ans;
}
#pragma endregion //繰り返し二乗法 powMod
#pragma region
template<class T>
vector<T> getDivisor(T n){
	vector<T> v;
	for(int i=1;i*i<=n;++i){
		if( n%i == 0 ){
			v.push_back(i);
			if( i != n/i ){//平方数で重複して数えないように
				v.push_back(n/i);
			}
		}
	}
	sort(v.begin(), v.end());
	return v;
}
#pragma endregion //約数列挙 getDivisor(n):O(√n)
#pragma endregion //math
//Utility:便利な奴
#pragma region
template<class T>
void UNIQUE(vector<T>& vec){
	sort(vec.begin(),vec.end());
	vec.erase(unique(vec.begin(),vec.end()),vec.end() );
}
#pragma endregion // sort erase unique
////////////////////////////////
#pragma region 
long long  bitcount64(long long bits)
{
    bits = (bits & 0x5555555555555555) + (bits >> 1 & 0x5555555555555555);
    bits = (bits & 0x3333333333333333) + (bits >> 2 & 0x3333333333333333);
    bits = (bits & 0x0f0f0f0f0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f0f0f0f0f);
    bits = (bits & 0x00ff00ff00ff00ff) + (bits >> 8 & 0x00ff00ff00ff00ff);
    bits = (bits & 0x0000ffff0000ffff) + (bits >>16 & 0x0000ffff0000ffff);
    return (bits & 0x00000000ffffffff) + (bits >>32 & 0x00000000ffffffff);
}
#pragma endregion //その他
////////////////////////////////
struct edge_base{int to;LL cost;};
edge_base make_edge_base(int to,LL cost){
	edge_base ret = {to,cost};
	return ret;
}
#pragma region GRL
#pragma region //グラフ
template<class T,class EDGE>
void dijkstra(int root,int V,vector<T>& dist,
	vector< vector<EDGE> > G	){
	priority_queue<pair<T,int>,vector<pair<T,int> >,greater<pair<T,int> > > que;
	dist.assign(V,LINF);
	dist[root] = 0;
	que.push(pair<T,int>(0,root));//距離、頂点番号

	while( !que.empty() ){
		pair<T,int> p = que.top();que.pop();
		int v = p.second;
		if( dist[v] < p.first ) continue;
		for(int i=0;i < (int)G[v].size();++i){
			EDGE e = G[v][i];
			if( dist[e.to] > dist[v] + e.cost ){
				dist[e.to] = dist[v] + e.cost;
				que.push(pair<T,int>(dist[e.to],e.to));
			}
		}
	}
}
#pragma endregion //ダイクストラ法:O(|E|log|V|)
#pragma region //グラフ
void warshall_floyd(vector<vector<LL> >& dist,int V,const LL INF=LINF){
	for(int k=0;k<V;++k){
		for(int i=0;i<V;++i){
			if( dist[i][k] >= INF ) continue;
			for(int j=0;j<V;++j){
				if( dist[k][j] >= INF )continue;
				dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
			}
		}
	}
}
#pragma endregion //ワーシャルフロイド:O(|V|**3)
#pragma region
namespace FLOW{
//vector< vector<FLOW:edge> > G;

struct edge_flow : public edge_base{
	int cap;
	int rev;
};
edge_flow make_edge_flow(int to,int cap,int rev,LL cost=1){
	edge_flow ret;
	
	ret.to = to;
	ret.cost = cost;
	ret.cap = cap;
	ret.rev = rev;
	return ret;
}
class Graph{
public:
	int V;
	vector< vector<FLOW::edge_flow> > G;
	vector< LL > dist;
	vector< int > iter;
	void init(int v){
		V = v;
		G.resize(V);
	}
	//directed graph
	void add_edge(int from,int to,int cap){
		G[from].push_back( FLOW::make_edge_flow(to,cap,G[to].size()) );
		G[to].push_back( FLOW::make_edge_flow(from,0,G[from].size()-1) );
	}
	
private:
	//sから最短距離をBFSで計算する
	void bfs(int s){//許容量もチェックしている
		queue<int> que;
		dist = vector<LL>(V,-1);
		dist[s] = 0;
		que.push(s);
		while(!que.empty()){
			int v = que.front();que.pop();
			for(int i=0;i<(int)G[v].size();++i){
				edge_flow &e = G[v][i];
				if( e.cap > 0 && dist[e.to] < 0 ){
					dist[e.to] = dist[v] + 1;
					que.push(e.to);
				}
			}
		}
	}
private:
	//増加パスをDFSで探す
	int dfs(int v,int t,int f){
		if( v==t ) return f;
		for(int &i = iter[v];i<(int)G[v].size();++i){//?
			FLOW::edge_flow &e = G[v][i];
			if( e.cap>0 && dist[v] < dist[e.to]){
				int d = this->dfs(e.to, t, min(f,e.cap) );
				if( d > 0){
					e.cap -= d;
					G[e.to][e.rev].cap += d;
					return d;
				}
			}
		}
		return 0;
	}
public:
	//sからtへの最大流量を求める
	int max_flow(int s,int t){
		int flow = 0;
		for(;;){
			this->bfs(s);
			if( dist[t] < 0 ) return flow;
			iter = vector<int>(V,0);
			int f;
			while( (f = this->dfs(s,t,INF) ) > 0 ){
				flow += f;
			}
		}
	}
};

}
#pragma endregion //dinic :O(|E||V|^2)
#pragma region //グラフ
bool is_bipartite(int v,int c,vector< vector<int> >& G,vector<int>& Color){
	Color[v] = c;
	for(int i=0;i < (int)G[v].size();++i){//隣接グラフ
		if(Color[ G[v][i] ] == c ) return false;
		if(Color[ G[v][i] ] == 0 && 
			!is_bipartite(G[v][i],-c,G,Color)
			){
				return false;
		}
	}
	return true;
}
bool is_bipartite(int Root,vector< vector<int> >& Graph){
	int GraphSize = Graph.size();
	vector<int> Color(GraphSize,0);
	const int ColorNo = 1;
	return is_bipartite(Root,ColorNo,Graph,Color);
}
#pragma endregion //二部グラフチェック is_bipartite(root,GraphList)
#pragma endregion //
#pragma region 
//http://sugarknri.hatenablog.com/entry/2016/07/16/165715
void makeinv(vector<LL>& inv,const LL P){
	int i;
	const int varMAX = 1000000;
	inv = vector<LL>( varMAX+1,0);
	inv[1]=1;
	for(i=2;i<=varMAX;i++){
		inv[i] = (inv[P%i] * (P-P/i)%P ) % P;//OVF
		//inv[i] = powMod(i,P-2,P);
	}
}

LL nCk(LL N,LL k,LL mod = MOD){
	static vector<LL> inv;//modの逆元
	if( inv.size() == 0 ){
		makeinv(inv,mod);//modは素数を入れる
	}
	k = min(k,N-k);
	if( k < 0 ){return 0;}
	if( k == 0 ){return 1;}
	if( k == 1 ){return N%mod;}
	LL ret = 1;
	for(int i=1;i<=k;++i){
		ret = (ret * ((N+1-i)%mod) )%mod;//ret*N:OVF
		ret = (ret * inv[i] )%mod;
		//ret *= ((N+1-i)*inv[i])%mod;//OVF
		//ret %= mod;
	}
	return ret;
}
LL nCk_once(LL N,LL k,LL mod = MOD){//modは素数
	k = min(k,N-k);
	if( k < 0 ){return 0;}
	if( k == 0 ){return 1;}
	if( k == 1 ){return N%mod;}
	LL ret = 1;
	LL A=1;
	for(LL i=0;i<k;++i){
		A = (A * ((N-i)%mod) ) % mod;
	}
	LL B=1;
	for(LL i=2;i<=k;++i){
		B = (B * (i%mod) ) % mod;
	}
	ret = ( A * powMod(B,mod-2,mod) ) % mod;
	return ret;
}
#pragma endregion //組み合わせnCk(,10^5)
#pragma region
vector< vector<LL> > NCK;
LL nCk_base(int N,int K,LL mod=MOD){
	K = min(K,N-K);
	if( K==0 ){return 1%mod;}
	if( K==1 ){return N%mod;}//%MOD;
	if( N<=10000 && NCK[N][K] ){
		return NCK[N][K];
	}
	//N個目を使わない:nCk(N-1,k)
	//N個目を使う	:nCk(N-1,k-1)
	LL ans = (nCk_base(N-1,K)+nCk_base(N-1,K-1) )%mod;//%MOD;
	if( N<=10000 ){
		NCK[N][K] = ans;
	}
	return ans;
}

#pragma endregion //組み合わせ メモ?
#pragma region CGL
class Point{
public:
	double x,y;
	Point(double x=0,double y=0):x(x),y(y){}

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

	double norm(){return sqrt(x*x+y*y);}
	double dot(Point p){return add(x*p.x,y*p.y);}
	double rot(Point p){return add(x*p.y,-y*p.x);}
	double add(double a,double b){
		double EPS = 1e-10;
		if( abs(a+b) < EPS*(abs(a)+abs(b)) ){
			return 0;
		}
		return a+b;
	}
};
istream& operator>>(istream& in,Point& P){
	in >> P.x >> P.y;
	return in;
}
bool operator<(Point A,Point B){
	if( A.x < B.x ) return true;
	else if( A.x > B.x ) return false;
	if( A.y < B.y ) return true;
	return false;
}

//線分で表した直線の交差判定
bool is_cross(Point p1,Point p2,Point q1,Point q2){
	double res = (p2-p1).rot(q2-q1);
	return  res != 0;//平行なら0
}

/*ccwへ//線分p1-p2上に点qがあるか判定
bool on_seg(Point p1,Point p2,Point q){
	return (p1-q).rot(p2-q) == 0 && (p1-q).dot(p2-q) <= 0;
}*/
//直線p1-p2と直線q1-q2の交点
//交差判定をしてから使う:0除算
Point intersection(Point p1,Point p2,Point q1,Point q2){
	return p1+(p2-p1)*((q2-q1).rot(q1-p1)/(q2-q1).rot(p2-p1));
}

//線分ABに対する点C
enum PointPotion{ONLINE_BACK=-2,CLOCKWISE,ON_SEGMENT,COUNTER_CLOCKWISE,ONLINE_FRONT};
PointPotion ccw(Point A,Point B,Point C){
	B -= A;C -=A;
	if( B.rot(C) > 0 ) return COUNTER_CLOCKWISE;//+1
	if( B.rot(C) < 0 ) return CLOCKWISE;//-1
	if( B.dot(C) < 0 ) return ONLINE_BACK;//-2
	if( B.norm() < C.norm() ) return ONLINE_FRONT;//+2
	return ON_SEGMENT;//0
}
//線分p1-p2,と線分q1-q2の交差判定
//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
bool intersect(Point p1,Point p2,Point q1,Point q2){
	return	(ccw(p1,p2,q1) * ccw(p1,p2,q2) <= 0) &&
			(ccw(q1,q2,p1) * ccw(q1,q2,p2) <= 0);
}
///
//直線p1-p2と点q1の距離
double dist_LineP(Point p1,Point p2,Point q1){
	return abs( (p2-p1).rot(q1-p1) )/(p2-p1).norm();
}
//線分p1-p2と点q1の距離
double dist_SegP(Point p1,Point p2,Point q1){
	//(日)
	if( (p2-p1).dot(q1-p1) < 0 ){
		return (q1-p1).norm();//p1から見てp2と逆方向
	}
	if( (p1-p2).dot(q1-p2) < 0 ){
		return (q1-p2).norm();//p2から見てp1と逆方向
	}
	return dist_LineP(p1,p2,q1);//垂線下ろす
}
// 線分同士の最短距離
//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
//http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=862507#1
double dist_segseg(Point A1,Point A2,Point B1,Point B2){
	if( intersect(A1,A2,B1,B2) ){
		return 0;
	}
	return min(
		min(dist_SegP(A1,A2,B1),
			dist_SegP(A1,A2,B2)
			),
		min(dist_SegP(B1,B2,A1),
			dist_SegP(B1,B2,A2)
			)
		);
}
#pragma endregion //class Point
#pragma region CGL
//多角形内なら2,線上なら1,外なら0
//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
//http://www.prefield.com/algorithm/geometry/contains.html
//点Pから半直線を引く、ガウス
int contains(vector<Point>& v,Point& P){
	bool in = false;
	const int N = v.size();
	for(int i=0;i<N;++i){
		Point A = (v[i]-P);
		Point B = (v[(i+1)%N]-P);
		if( A.y > B.y ) swap(A,B);
		if( A.y <= 0 && 0 < B.y ){
			if( A.rot(B) < 0 ) in =!in;
		}
		if( A.rot(B) == 0 && A.dot(B) <= 0 ){
			return 1;//ON 線上
		}
	}
	return in ? 2:0;//中:外
}
#pragma endregion //contains
#pragma region CGL
//辞書順で比較
bool cmp_x(const Point& p,const Point& q){
	if( p.x != q.x ) return p.x < q.x;
	return p.y < q.y;
}

//凸包を求める
vector<Point> convex_hull(vector<Point> ps,int n){
	sort(ps.begin(),ps.end(), cmp_x);
	int k = 0;//凸包の頂点数
	vector<Point> qs(n*2);//構築中の凸包
	//下側の凸包の作成
	for(int i=0;i<n;++i){
		while(k>1 && (qs[k-1]-qs[k-2]).rot(ps[i]-qs[k-1]) <=0){//<で線上も加える
			k--;
		}
		qs[k++] = ps[i];
	}
	//上側凸包の作成
	for(int i=n-2,t=k;i>=0;i--){
		while(k>t && (qs[k-1]-qs[k-2]).rot(ps[i]-qs[k-1]) <=0){//<
			k--;
		}
		qs[k++] = ps[i];
	}
	qs.resize(k-1);
	return qs;
}
#pragma endregion //凸包
#pragma region DSL
#pragma region DSL
class UnionFind{
public:
	int cNum;//要素数
	vector<int> parent;
	vector<int> count;
	vector< vector<int> > GList;
	UnionFind(int n){
		cNum = n;
		parent = vector<int>(n);
		count = vector<int>(n,1);
		GList.resize(n);
		for(int i=0;i<n;++i){
			parent[i] = i;
			GList[i].push_back(i);
		}
	}
	int find(int x){
		if( parent[x] == x ){return x;}
		return parent[x] = find( parent[x] );
	}
	bool same(int x,int y){return find(x) == find(y);}
	int Count(int x){return count[find(x)];}
	void add(int x,int y){//union
		x = find(x);
		y = find(y);
		if( x==y )return;
		parent[x] = y;
		count[y] += count[x];
		if( GList[y].size() < GList[x].size() ){
			swap(GList[x],GList[y]);
		}
		GList[y].insert( GList[y].end(),
			GList[x].begin(),GList[x].end() );
	}
};
#pragma endregion //UnionFind
#pragma region DSL
class segment{
	int n;
	int OTHER_VAL;
	int NUM_NULL;
	vector< int > dat;
public:
	int getN(){return n;}
	void init(int size,int num=INF,int num_null=-1){//N:要素数,最大値
		OTHER_VAL = num;
		NUM_NULL = num_null;
		n = 2;
		while(n < size ){
			n <<= 1;
		}
		dat.assign(n<<1, OTHER_VAL );
	}
	void init(vector<int> vec,int size,int num=INF){
		OTHER_VAL = num;
		n = 2;
		while(n < size ){
			n <<= 1;
		}
		dat.assign(n<<1,OTHER_VAL );
		for(int i=0;i<size;++i){
			update(i,vec[i]);
		}
	}
	int SELECT(int L,int R){
		return min(L,R);
	}
	void update(int i,int x){
		i += n;
		while(i){
			dat[i] = SELECT(dat[i],x);
			i >>= 1;
		}
	}
	void update(int X,int Y,int VAL){
		//全体の範囲は閉区間、
		update(1,0,n-1,X,Y,VAL);
	}
private:
	void update(int t,int L,int R,int X,int Y,int VAL){
		//親から子へ進んでいく
		if( L == X && R == Y){
			dat[t] = VAL;
		}else{
			int mid = (L+R)/2;
			if( dat[t] != NUM_NULL ){//値の伝播
				dat[t*2+0] = dat[t];
				dat[t*2+1] = dat[t];
				dat[t] = NUM_NULL;
			}
			if( Y <= mid ){
				update(t*2+0,L,mid,X,Y,VAL);
			}else if( X > mid ){
				update(t*2+1,mid+1,R,X,Y,VAL);
			}else{
				update(t*2+0,L,mid,X,mid,VAL);
				update(t*2+1,mid+1,R,mid+1,Y,VAL);
			}
		}
	}
public:
	//query(a,b,0,0,n)//[a,b)半開区間
	int query(int a,int b){
		return query(a,b,1,0,n);//n==getNを使う
	}
private:
	int query(int a,int b,int k,int l,int r){
		if(r<=a || b<=l)return OTHER_VAL;//交差しない
		if(a<=l && r<=b && dat[k]!=NUM_NULL)return dat[k];

		int res = OTHER_VAL;
		int mid = (l+r)>>1;
		if( a < mid ) res = SELECT(res,query(a,b,k*2+0,l,mid) );
		if( mid < b ) res = SELECT(res,query(a,b,k*2+1,mid,r) );
		return res;
	}
};
#pragma endregion //segment tree
#pragma region DSL
class BITree{//1-index
	int N;
	vector<LL> bit;
public:
	BITree(int n){
		N = n;
		bit = vector<LL>(N+1,0);//1-index
	}
	void add(int a,LL w){
		for(int i=a;i<=N;i += i & -i){
			bit[i] += w;
		}
	}
	LL sum(int a){//[1,a)の和
		LL ret = 0;
		for(int i=a; i > 0; i -= i & -i){
			ret += bit[i];
		}
		return ret;
	}
};
#pragma endregion //BIndexTree
#pragma endregion //

#pragma region 
template<class T,class U>
istream& operator>>(istream& in,pair<T,U>& P){
	in >> P.first >> P.second;
	return in;
}
#pragma endregion //cin pair<T,U>
#pragma region 
template<class T>
istream& operator>>(istream& in,vector<T>& v){
	int size = v.size();
	for(int i=0;i<size;++i){
		in >> v[i];
	}
	return in;
}
#pragma endregion //cin vector<int>
#pragma region 
//行列の積
template<class T>
vector< vector<T> > operator*( vector<vector<T> >& A,vector< vector<T> >& B){
	LL mod = MOD;
	int R = A.size();
	int cen = A[0].size();
	int C = B[0].size();
	vector< vector<T> > ans(R,vector<T>(C,0) );
	for(int row=0;row<R;++row){
		for(int col=0;col<C;++col){
			for(int inner=0;inner< cen;++inner){
				ans[row][col] = (ans[row][col] + A[row][inner]*B[inner][col])%mod;
				//ans[row][col] = (ans[row][col] + A[row][inner]*B[inner][col]);
			}
		}
	}
	return ans;
}

template<class T>
vector< vector<T> > powMod(vector< vector<T> > mat,LL N){
	int R = mat.size();
	int C = mat[0].size();
	//R==C
	vector< vector<T> > I(R,vector<T>(C,0));//単位元
	for(int i=0;i<R && i<C;++i){
		I[i][i] = 1;
	}
	if( N == 0 ){
		return I;
	}
	vector< vector<T> > mul(R,vector<T>(C)),ans(R,vector<T>(C));
	ans = I;
	mul = mat;
	while(N){
		if( N & 1 ){
			ans = ans*mul;
		}
		N >>= 1;
		mul = mul*mul;
	}
	return ans;
}
#pragma endregion //行列

#pragma region
namespace TIME{
time_t start,limit;
void time_start(){start = time(NULL);}
void time_set(int num){limit = num;}//秒
bool check(){return (time(NULL)-start < limit);}
}
#pragma endregion //時間計測
/*
#pragma region
namespace RAND{
mt19937 mt;
void rand_init(){
	random_device rnd;
	mt = mt19937(rnd());
}
int rand(){
	return mt();
}
}
#pragma endregion //乱数
*/
#pragma region
#pragma endregion //
////////////////////
#pragma region
double area(vector<Point> poly){
	int size = poly.size();
	double ans = 0;
	for(int i=1;i<size-1;++i){
		ans += (poly[i]-poly[0]).rot(poly[i+1]-poly[0])/2;
	}
	return ans;
}
#pragma endregion //多角形の面積
////////////////////
#pragma region CGL
bool compare_x(Point A,Point B){
	return A.x < B.x;
}
bool compare_y(Point A,Point B){
	return A.y < B.y;
}
//vecはx座標の昇順で渡される
double closest_pair(vector<Point>::iterator itr,int N){
	if(  N <= 1 ) return INF;
	int m = N/2;
	double x = (itr+m)->x;
	double d = min(closest_pair(itr,m),
		closest_pair((itr+m),N-m) );
	
	inplace_merge(itr,itr+m,itr+N,compare_y);

	vector<Point> B;
	for(int i=0;i<N;++i){
		if(fabs((itr+i)->x - x) >= d) continue;
		int Bsize = B.size();
		for(int j=0;j<Bsize;j++){
			double dx,dy;
			dx = (itr+i)->x - B[Bsize-j-1].x;
			dy = (itr+i)->y - B[Bsize-j-1].y;
			if( dy >= d ) break;
			d = min(d,hypot(dx,dy));
		}
		B.push_back(*(itr+i));
	}
	return d;
}
#pragma endregion //最近対 2D
////////////////////
#pragma region
int CircleIntersection(Point A,double AR,Point B,double BR){
	double D = (B-A).norm();
	if( D > AR+BR ){
		return 4;
	}else if( D == AR+BR ){
		return 3;
	}else if( abs(AR-BR) < D  ){//&& D<AR+BR
		return 2;
	}else if(D == abs(AR-BR)){
		return 1;
	}else if(D+AR < BR || D+BR<AR){
		return 0;
	}
	return 0;//
}
#pragma endregion //円と円の位置関係

#pragma region
vector<Point> CircleLine(Point C,double CR,Point A,Point B){
	vector<Point> ans(2);//同じ交点なら同じ値
	double a,b,c;
	a = -(A.y-B.y);
	b = A.x-B.x;
	c = -(a*A.x+b*A.y);

	double l,k,d;
	l = a*a+b*b;
	k = a*C.x + b*C.y+ c;
	d = l*CR*CR-k*k;
	if(d>0){
		double ds = sqrt(d);
		double apl = a/l;
		double bpl = b/l;
		double xc = C.x-apl*k;
		double yc = C.y-bpl*k;
		double xd = bpl*ds;
		double yd = apl*ds;
		Point temp;
		ans[0].x = xc-xd;
		ans[0].y = yc+yd;
		ans[1].x = xc+xd;
		ans[1].y = yc-yd;
	}else if(d==0){
		Point temp;
		temp.x = C.x-a*k/l;
		temp.y = C.y-b*k/l;
		ans[0] = temp;
		ans[1] = temp;
	}else{
		Point temp;
		temp.x = INF;
		temp.y = INF;
		ans[0] = temp;
		ans[1] = temp;
	}
	return ans;
}
#pragma endregion //円と直線の交点,距離チェックする。
//////////////////
//行列式
/////////////////

void solve(){
	int N;
	cin >> N;
	vector< pair<LL,LL> > XY(N);
	vector< pair<LL,int> > A(2*N);
	for(int i=0;i<N;++i){
		cin >> XY[i].first >> XY[i].second;
		if( XY[i].first > XY[i].second ){
			swap(XY[i].first,XY[i].second);
		}
		A[2*i+0].first = XY[i].first;
		A[2*i+0].second = i;
		A[2*i+1].first = XY[i].second;
		A[2*i+1].second = i;
	}
	sort( XY.begin(), XY.end() );
	sort( A.begin(), A.end() );
	LL Rmax,Rmin,Bmax,Bmin;
	//全体のmax,minが別の色
	LL ans = -1;
	{
		int minPos = A[0].second;
		int maxPos = A[2*N-1].second;
		Rmax = A[2*N-1].first;
		Rmin = INF;
		Bmax = 0;
		Bmin = A[0].first;
		for(int i=0;i<N;++i){
			if( i == minPos ){
				Rmin = min(Rmin,XY[i].second);
			}else if( i == maxPos){
				Bmax = max(Bmax,XY[i].first);
			}else{
				Rmin = min(Rmin,XY[i].second);
				Bmax = max(Bmax,XY[i].first);
			}
		}
		ans = (Rmax-Rmin)*(Bmax-Bmin);
	}
	//全体のmax,minが同じ色
	if(A[0].second == A[2*N-1].second){//同じ箱だと同じ色に出来ない
		cout << ans << endl;
		return;
	}
	Rmin =A[0].first;
	Rmax =A[2*N-1].first;
	LL Rwide = Rmax-Rmin;

	vector< pair<LL,LL> > XX(N),YY(N);//min,max
	for(int i=0;i<N;++i){
		if( i == 0 ){
			YY[i].first = XY[i].first;
			YY[i].second = XY[i].second;
		}else{
			YY[i].first = min(YY[i-1].first,XY[i].first);
			YY[i].second = max(YY[i-1].second,XY[i].second);
		}
	}
	for(int i=N-1;i>=0;--i){
		if( i == N-1 ){
			XX[i].first = XY[i].first;
			XX[i].second = XY[i].second;
		}
		else{
			XX[i].first = min(XX[i+1].first,XY[i].first);
			XX[i].second = max(XX[i+1].second,XY[i].second);
		}
	}
	for(int i=0;i<N-1;++i){
		LL MIN,MAX;
		MIN = YY[i].first;
		MIN = min(MIN,XX[i+1].first);

		MAX = YY[i].second;
		MAX = max(MAX,XX[i+1].second);
		LL res = Rwide*(MAX-MIN);
		ans = min(ans,res);
	}
	cout << ans << endl;
}

#pragma region main
signed main(void){
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	std::cout << std::fixed;//小数を10進数表示
	cout << setprecision(16);//小数点以下の桁数を指定//coutとcerrで別	
	
	solve();
}
#pragma endregion //main()