use std::collections::*;
use std::io::Write;
type Map<K, V> = BTreeMap<K, V>;
type Set<T> = BTreeSet<T>;
type Deque<T> = VecDeque<T>;
fn main() {
input! {
n: usize,
p: [(i64, i64, i64, i64); n],
}
let mut l = CHT::new(p.iter().map(|p| (-p.2, -p.0)).collect());
let mut r = CHT::new(p.iter().map(|p| (p.2, p.0)).collect());
let mut d = CHT::new(p.iter().map(|p| (-p.3, -p.1)).collect());
let mut u = CHT::new(p.iter().map(|p| (p.3, p.1)).collect());
let mut x = vec![0f64];
x.extend(l.enumerate());
x.extend(r.enumerate());
x.extend(d.enumerate());
x.extend(u.enumerate());
x.sort_by(|a, b| a.partial_cmp(b).unwrap());
x.retain(|x| *x >= 0f64);
let mut ans = std::f64::MAX;
for x in x {
ans = ans.min((r.find(x) + l.find(x)) * (u.find(x) + d.find(x)));
}
println!("{:.10}", ans);
}
// max cht
struct CHT {
po: usize,
line: Vec<(i64, i64)>, // (a, b) ax + b
}
impl CHT {
fn new(mut line: Vec<(i64, i64)>) -> Self {
line.sort();
line.dedup_by(|a, b| a.0 == b.0);
let mut stack = vec![line[0]];
for &(a, b) in line[1..].iter() {
while stack.len() >= 2 {
let len = stack.len();
let (c, d) = stack[len - 1];
let (e, f) = stack[len - 2];
//if (d - b) / (a - c) <= (
if (d - b) * (a - e) <= (f - b) * (a - c) {
stack.pop();
} else {
break;
}
}
stack.push((a, b));
}
Self { line: stack, po: 0 }
}
fn find(&mut self, x: f64) -> f64 {
let find = |k: usize| -> f64 {
let (a, b) = self.line[k];
a as f64 * x + b as f64
};
while self.po + 1 < self.line.len() && find(self.po) <= find(self.po + 1) {
self.po += 1;
}
find(self.po)
}
fn enumerate(&self) -> Vec<f64> {
self.line.windows(2).map(|line| {
let (a, b) = line[0];
let (c, d) = line[1];
(b - d) as f64 / (c - a) as f64
}).collect()
}
}
// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
#[macro_export]
macro_rules! input {
(source = $s:expr, $($r:tt)*) => {
let mut iter = $s.split_whitespace();
input_inner!{iter, $($r)*}
};
($($r:tt)*) => {
let s = {
use std::io::Read;
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
s
};
let mut iter = s.split_whitespace();
input_inner!{iter, $($r)*}
};
}
#[macro_export]
macro_rules! input_inner {
($iter:expr) => {};
($iter:expr, ) => {};
($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($iter, $t);
input_inner!{$iter $($r)*}
};
}
#[macro_export]
macro_rules! read_value {
($iter:expr, ( $($t:tt),* )) => {
( $(read_value!($iter, $t)),* )
};
($iter:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
};
($iter:expr, chars) => {
read_value!($iter, String).chars().collect::<Vec<char>>()
};
($iter:expr, bytes) => {
read_value!($iter, String).bytes().collect::<Vec<u8>>()
};
($iter:expr, usize1) => {
read_value!($iter, usize) - 1
};
($iter:expr, $t:ty) => {
$iter.next().unwrap().parse::<$t>().expect("Parse error")
};
}
// ---------- end input macro ----------