#include <bits/stdc++.h>
using namespace std;

#define llong long long 
#define len(x) ((int)x.size())
#define rep(i,n) for (int i = -1; ++ i < n; )
#define rep1(i,n) for (int i = 0; i ++ < n; )
#define rand __rand
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());  // or mt19937_64
template<class T = int> T rand(T range = numeric_limits<T>::max()) { return (T)(rng() % range); }

#define CONCAT_(x, y) x##y/*{{{*/
#define CONCAT(x, y) CONCAT_(x, y)
#define SPEC(name) CONCAT(name, __LINE__)
#ifdef LOCAL_DEBUG   
int __db_level = 0;
#define clog cerr << string(__db_level * 2, ' ')
struct debug_block {
    string msg;
    debug_block(const string& s): msg(s) { clog << "{ " << msg << endl; ++__db_level; }
    ~debug_block() { --__db_level; clog << "} " << msg << endl; }
};
#define DB(args...) stringstream SPEC(ss); SPEC(ss)<< args; debug_block SPEC(dbbl)(SPEC(ss).str())
#else
#define clog if (0) cerr
#define DB(...)
#endif
#define db(val) "[" #val " = " << val << "]; "
template<class U, class V> ostream& operator<<(ostream& out, const pair<U, V>& p) {
    return out << "(" << p.first << ", " << p.second << ")";
}
template<size_t i, class T> ostream& print_tuple_utils(ostream& out, const T& tup) {
    if constexpr(i == tuple_size<T>::value) return out << ")";
    else return print_tuple_utils<i + 1, T>(out << (i ? ", " : "(") << get<i>(tup), tup);
}
template<class ...U>
ostream& operator<<(ostream& out, const tuple<U...>& tup) { return print_tuple_utils<0, tuple<U...>>(out, tup); }
template<class, typename = void> struct has_const_iterator : false_type {};
template<class T> struct has_const_iterator<T, void_t<typename T::const_iterator>> : true_type {};
template<class T>
typename enable_if<has_const_iterator<T>::value && !is_same<T, string>::value, ostream&>::type
operator<<(ostream& out, const T& container) { 
    auto beg = container.begin(), end = container.end();
    out << "(" << container.size() << ") {";
    if (beg != end) out << *(beg++);
    while (beg != end) out << ", " << *(beg++);
    return out << "}";
}
#define ptrtype(x) typename iterator_traits<x>::value_type
template<class u> vector<ptrtype(u)> $v(u a, u b) { return vector<ptrtype(u)>(a, b); }/*}}}*/
// ACTUAL SOLUTION BELOW ////////////////////////////////////////////////////////////

struct BIT {
    vector<llong> val;
    BIT(int n): val(n + 10, LLONG_MAX) {}
    
    void upd(int pos, llong del) {
        for (++pos; pos < len(val); pos += pos & -pos) val[pos] = min(val[pos], del);
    }
    
    llong get(int pos) {
        llong ans = LLONG_MAX;
        for (++pos; pos > 0; pos -= pos & -pos) ans = min(ans, val[pos]);
        return ans;
    }
};

const int maxn = 201010;
using point = pair<llong, llong>;
int n;
point a[maxn];

llong solve(function<point(point)> transform) {
    vector<point> p(n);
    rep(i, n) p[i] = transform(a[i]);
    
    sort(p.begin(), p.end());
    
    vector<llong> y_vals;
    for (auto& [x, y]: p) y_vals.push_back(y);
    sort(y_vals.begin(), y_vals.end());
    
    y_vals.erase(unique(y_vals.begin(), y_vals.end()), y_vals.end());
    
    BIT bit(len(y_vals));
    llong ans = 0;
    for (auto& [x, y]: p) {
        int y_pos = (int)(lower_bound(y_vals.begin(), y_vals.end(), y) - y_vals.begin());
        
        llong cur_val = bit.get(y_pos);
        
        if (cur_val < LLONG_MAX) ans = max(ans, x + y - cur_val);
        bit.upd(y_pos, x + y);
    }
    return ans;
}

// #define testing 
int main(void) {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef testing
    cin >> n;
    rep(i, n) cin >> a[i].first >> a[i].second;
#else
    while (true) {
    ofstream inp("main.inp");
    n = 10;
    inp << n << endl;
    rep(i, n) {
        a[i].first = rand(100) - 200;
        a[i].second = rand(100) - 200;
        inp << a[i].first << ' ' << a[i].second << endl;
    }
#endif
    
    llong ans = 0;
    for (auto& trans: initializer_list<function<point(point)>> {
            [](point p) -> point { return p; },
            [](point p) -> point { return {-p.first, p.second}; },
            [](point p) -> point { return {p.second, p.first}; },
            [](point p) -> point { return {-p.second, p.first}; }
    }) {
        ans = max(ans, solve(trans));
    }
#ifndef testing
    cout << ans;
#else
    clog << "OK" << endl;
#endif
    

#ifdef testing
    }
#endif

    return 0;
}

// Remember:
// - Multitest? REFRESHING the data!!!
// - Constrains for each set of data may differs. Should NOT USE the same max constant (maxn)
//   for all of them.
// vim: foldmethod=marker



Measured memory_bytes: 13252