#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <set>
using namespace std;
typedef pair<int, int> P;
#define X first
#define Y second

struct rcomp{
    bool operator()(const P &a, const P &b){
        return (a.Y != b.Y)? a.Y<b.Y: a.X<b.X;
    }
};

int main(){
    int n;
    cin >> n;
    set<P> pxf;
    set<P, rcomp> pyf;
    for(int i=0; i<n; i++){
        int x,y;
        cin >> x >> y;
        pxf.insert(P(x+y, x-y));
        pyf.insert(P(x+y, x-y));
    }

    //まず最遠点を分ける
    P fp[2];
    if((*pxf.rbegin()).X -(*pxf.begin()).X > (*pyf.rbegin()).Y -(*pyf.begin()).Y){
        fp[0] = *pxf.begin();
        fp[1] = *pxf.rbegin();
    }else{
        fp[0] = *pyf.begin();
        fp[1] = *pyf.rbegin();
    }
    pxf.erase(fp[0]);
    pxf.erase(fp[1]);
    pyf.erase(fp[0]);
    pyf.erase(fp[1]);

    //分割するグループ
    set<P> axf, bxf;
    set<P, rcomp> ayf, byf;
    axf.insert(fp[0]);
    ayf.insert(fp[0]);
    bxf.insert(fp[1]);
    byf.insert(fp[1]);

    while(!pxf.empty()){
        P p1 = *pxf.begin();
        pyf.erase(p1);
        pxf.erase(p1);
        //最も遠い点が、A,B、未処理のどこにあるか判定
        //(ソート済みの最初と最後だけ見ればいい)
        int dax = max(abs((*axf.begin()).X -p1.X), abs((*axf.rbegin()).X -p1.X));
        int day = max(abs((*ayf.begin()).Y -p1.Y), abs((*ayf.rbegin()).Y -p1.Y));
        int dbx = max(abs((*bxf.begin()).X -p1.X), abs((*bxf.rbegin()).X -p1.X));
        int dby = max(abs((*byf.begin()).Y -p1.Y), abs((*byf.rbegin()).Y -p1.Y));
        int dpx = 0;
        int dpy = 0;
        if(!pxf.empty()){
            dpx = max(abs((*pxf.begin()).X -p1.X), abs((*pxf.rbegin()).X -p1.X));
            dpy = max(abs((*pyf.begin()).Y -p1.Y), abs((*pyf.rbegin()).Y -p1.Y));    
        } 
        int da = max(dax, day);
        int db = max(dbx, dby);
        int dp = max(dpx, dpy);

        //Aの場合はBに、Bの場合はAに入れる
        if(da >= max(db, dp)){
            bxf.insert(p1);
            byf.insert(p1);
        }else if(db >= max(da, dp)){
            axf.insert(p1);
            ayf.insert(p1);
        }else{
            //未処理の場合は、未処理最遠点対をA,Bに分けて入れる
            //未処理最遠点を取り出す
            P p2;
            if(dpx > dpy){
                if(abs((*pxf.begin()).X -p1.X) > abs((*pxf.rbegin()).X -p1.X)){
                    p2 = *pxf.begin();     
                }else{
                    p2 = *pxf.rbegin();
                }
            }else{
                if(abs((*pyf.begin()).Y -p1.Y) > abs((*pyf.rbegin()).Y -p1.Y)){
                    p2 = *pyf.begin();     
                }else{
                    p2 = *pyf.rbegin();
                }
            }
            pxf.erase(p2);
            pyf.erase(p2);

            //ロスの少ないほうに入れる
            int dax2 = max(abs((*axf.begin()).X -p2.X), abs((*axf.rbegin()).X -p2.X));
            int day2 = max(abs((*ayf.begin()).Y -p2.Y), abs((*ayf.rbegin()).Y -p2.Y));
            int dbx2 = max(abs((*bxf.begin()).X -p2.X), abs((*bxf.rbegin()).X -p2.X));
            int dby2 = max(abs((*byf.begin()).Y -p2.Y), abs((*byf.rbegin()).Y -p2.Y));
            int da2 = max(dax2, day2);
            int db2 = max(dbx2, dby2);
            if(max(da, db2) > max(db, da2)){
                swap(p1, p2);
            }
            axf.insert(p1);
            ayf.insert(p1);
            bxf.insert(p2);
            byf.insert(p2);
        }
    }
    cout << max(max((*axf.rbegin()).X -(*axf.begin()).X, (*ayf.rbegin()).Y -(*ayf.begin()).Y),
                max((*bxf.rbegin()).X -(*bxf.begin()).X, (*byf.rbegin()).Y -(*byf.begin()).Y) )
            << endl;
    return 0;
}



Measured memory_bytes: 12452