#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘)f=-1; ch=getchar();}
while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
return x*f;
}
#define inf 0x7fffffff
#define maxn 500010
int n,D,ans;
struct PointNode
{
int l,r; int d[2],maxx[2],minn[2];
PointNode (int x=0,int y=0) {l=r=0; d[0]=x,d[1]=y;}
bool operator < (const PointNode & A) const {return d[D]<A.d[D];}
}p[maxn];
int dis(PointNode A,PointNode B) {return abs(A.d[1]-B.d[1])+abs(A.d[0]-B.d[0]);}
struct KDTreeNode
{
PointNode tree[maxn<<1],Point;
int rt,ansMax,ansMin;
void Update(int now)
{
for (int i=0; i<=1; i++)
{
tree[now].minn[i]=tree[now].maxx[i]=tree[now].d[i];
if (tree[now].l)
tree[now].minn[i]=min(tree[tree[now].l].minn[i],tree[now].minn[i]),
tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]);
if (tree[now].r)
tree[now].minn[i]=min(tree[tree[now].r].minn[i],tree[now].minn[i]),
tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]);
}
}
int BuildTree(int l,int r,int dd)
{
int mid=(l+r)>>1;
D=dd; nth_element(p+l,p+mid,p+r+1);
tree[mid]=p[mid];
for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i];
if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1);
if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1);
Update(mid);
return mid;
}
int disMax(int now)
{
if (!now) return -inf;
int re=0;
for (int i=0; i<=1; i++)
re+=max(abs(tree[now].maxx[i]-Point.d[i]),abs(tree[now].minn[i]-Point.d[i]));
return re;
}
int disMin(int now)
{
if (!now) return inf;
int re=0;
for (int i=0; i<=1; i++) re+=max(0,tree[now].minn[i]-Point.d[i]);
for (int i=0; i<=1; i++) re+=max(0,Point.d[i]-tree[now].maxx[i]);
return re;
}
void GetMax(int now)
{
if (!now) return;
int dl,dr,d0;
d0=dis(tree[now],Point);
ansMax=max(d0,ansMax);
if (tree[now].l) dl=disMax(tree[now].l);
if (tree[now].r) dr=disMax(tree[now].r);
if (dl>dr)
{
if (dl>ansMax) GetMax(tree[now].l);
if (dr>ansMax) GetMax(tree[now].r);
}
else
{
if (dr>ansMax) GetMax(tree[now].r);
if (dl>ansMax) GetMax(tree[now].l);
}
}
void GetMin(int now)
{
if (!now) return;
int dl,dr,d0;
d0=dis(tree[now],Point);
if (d0) ansMin=min(ansMin,d0);
if (tree[now].l) dl=disMin(tree[now].l);
if (tree[now].r) dr=disMin(tree[now].r);
if (dl<dr)
{
if (dl<ansMin) GetMin(tree[now].l);
if (dr<ansMin) GetMin(tree[now].r);
}
else
{
if (dr<ansMin) GetMin(tree[now].r);
if (dl<ansMin) GetMin(tree[now].l);
}
}
int QueryMax(PointNode P) {Point=P; ansMax=-inf; GetMax(rt); return ansMax;}
int QueryMin(PointNode P) {Point=P; ansMin=inf; GetMin(rt); return ansMin;}
}KDTree;
int main()
{
n=read();
for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i].d[0]=x,p[i].d[1]=y;
for (int i=0; i<=1; i++) p[0].maxx[i]=-inf,p[0].minn[i]=inf;
KDTree.rt=KDTree.BuildTree(1,n,1);
ans=inf;
for (int i=1; i<=n; i++)
{
int minn=KDTree.QueryMin(p[i]),maxx=KDTree.QueryMax(p[i]);
ans=min(ans,maxx-minn);
}
printf("%d\n",ans);
return 0;
}