package main
import (
"bufio"
"fmt"
"os"
"sort"
)
type Point struct {
x int64
y int64
}
type DSU struct {
p []int
r []int
}
func NewDSU(n int) *DSU {
p := make([]int, n)
r := make([]int, n)
for i := 0; i < n; i++ {
p[i] = i
}
return &DSU{p: p, r: r}
}
func (d *DSU) Find(x int) int {
for d.p[x] != x {
d.p[x] = d.p[d.p[x]]
x = d.p[x]
}
return x
}
func (d *DSU) Union(a, b int) {
ra := d.Find(a)
rb := d.Find(b)
if ra == rb {
return
}
if d.r[ra] < d.r[rb] {
ra, rb = rb, ra
}
d.p[rb] = ra
if d.r[ra] == d.r[rb] {
d.r[ra]++
}
}
func max64(a, b int64) int64 {
if a > b {
return a
}
return b
}
func min64(a, b int64) int64 {
if a < b {
return a
}
return b
}
var (
n int
pts []Point
xs []int64
ys []int64
cols [][]int
rows [][]int
occupied []bool
Ux int
Uy int
)
func check(t int64) bool {
dsu := NewDSU(n)
for _, list := range cols {
for i := 1; i < len(list); i++ {
if pts[list[i]].y-pts[list[i-1]].y <= t {
dsu.Union(list[i], list[i-1])
}
}
}
for _, list := range rows {
for i := 1; i < len(list); i++ {
if pts[list[i]].x-pts[list[i-1]].x <= t {
dsu.Union(list[i], list[i-1])
}
}
}
compOf := make([]int, n)
compMap := make(map[int]int, n)
c := 0
for i := 0; i < n; i++ {
r := dsu.Find(i)
id, ok := compMap[r]
if !ok {
id = c
compMap[r] = id
c++
}
compOf[i] = id
}
if c == 1 {
return true
}
if c > 4 {
return false
}
allmask := uint8((1 << c) - 1)
if c == 2 {
for _, list := range cols {
for i := 1; i < len(list); i++ {
a, b := list[i-1], list[i]
if compOf[a] == compOf[b] {
continue
}
ya, yb := pts[a].y, pts[b].y
lo := max64(ya+1, yb-t)
hi := min64(yb-1, ya+t)
if lo <= hi {
return true
}
}
}
for _, list := range rows {
for i := 1; i < len(list); i++ {
a, b := list[i-1], list[i]
if compOf[a] == compOf[b] {
continue
}
xa, xb := pts[a].x, pts[b].x
lo := max64(xa+1, xb-t)
hi := min64(xb-1, xa+t)
if lo <= hi {
return true
}
}
}
}
v := make([]uint8, Ux*Uy)
for cx, list := range cols {
pos := 0
m := len(list)
base := cx * Uy
for cy, Y := range ys {
for pos < m && pts[list[pos]].y < Y {
pos++
}
var mask uint8
if pos > 0 {
p := list[pos-1]
if Y-pts[p].y <= t {
mask |= uint8(1 << compOf[p])
}
}
a := pos
if a < m && pts[list[a]].y == Y {
a++
}
if a < m {
p := list[a]
if pts[p].y-Y <= t {
mask |= uint8(1 << compOf[p])
}
}
v[base+cy] = mask
}
}
for cy, list := range rows {
pos := 0
m := len(list)
for cx, X := range xs {
for pos < m && pts[list[pos]].x < X {
pos++
}
var mask uint8
if pos > 0 {
p := list[pos-1]
if X-pts[p].x <= t {
mask |= uint8(1 << compOf[p])
}
}
a := pos
if a < m && pts[list[a]].x == X {
a++
}
if a < m {
p := list[a]
if pts[p].x-X <= t {
mask |= uint8(1 << compOf[p])
}
}
idx := cx*Uy + cy
if !occupied[idx] && (v[idx]|mask) == allmask {
return true
}
}
}
return false
}
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
fmt.Fscan(in, &n)
pts = make([]Point, n)
colMap := make(map[int64][]int)
rowMap := make(map[int64][]int)
for i := 0; i < n; i++ {
fmt.Fscan(in, &pts[i].x, &pts[i].y)
colMap[pts[i].x] = append(colMap[pts[i].x], i)
rowMap[pts[i].y] = append(rowMap[pts[i].y], i)
}
xs = make([]int64, 0, len(colMap))
for x := range colMap {
xs = append(xs, x)
}
sort.Slice(xs, func(i, j int) bool { return xs[i] < xs[j] })
ys = make([]int64, 0, len(rowMap))
for y := range rowMap {
ys = append(ys, y)
}
sort.Slice(ys, func(i, j int) bool { return ys[i] < ys[j] })
Ux = len(xs)
Uy = len(ys)
xid := make(map[int64]int, Ux)
for i, x := range xs {
xid[x] = i
}
yid := make(map[int64]int, Uy)
for i, y := range ys {
yid[y] = i
}
cols = make([][]int, Ux)
for x, list := range colMap {
sort.Slice(list, func(i, j int) bool {
return pts[list[i]].y < pts[list[j]].y
})
cols[xid[x]] = list
}
rows = make([][]int, Uy)
for y, list := range rowMap {
sort.Slice(list, func(i, j int) bool {
return pts[list[i]].x < pts[list[j]].x
})
rows[yid[y]] = list
}
occupied = make([]bool, Ux*Uy)
for _, p := range pts {
occupied[xid[p.x]*Uy+yid[p.y]] = true
}
high := int64(2000000000)
if !check(high) {
fmt.Fprintln(out, -1)
return
}
low := int64(-1)
for high-low > 1 {
mid := (low + high) / 2
if check(mid) {
high = mid
} else {
low = mid
}
}
fmt.Fprintln(out, high)
}