#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
using ll = long long;
typedef pair<ll,ll> P;
ll Mod = 1000000007;
ll INF = Mod * 1000LL;

ll f(ll a,ll b) {
  return min(a,b);
}


template< typename Monoid >
struct SegmentTree {
  using F = function< Monoid(Monoid, Monoid) >;

  int sz;
  vector< Monoid > seg;

  const F f;
  const Monoid M1;

  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while(sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }

  void set(int k, const Monoid &x) {
    seg[k + sz] = x;
  }

  void build() {
    for(int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while(k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) L = f(L, seg[a++]);
      if(b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }

  Monoid operator[](const int &k) const {
    return seg[k + sz];
  }

  template< typename C >
  int find_subtree(int a, const C &check, Monoid &M, bool type) {
    while(a < sz) {
      Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
      if(check(nxt)) a = 2 * a + type;
      else M = nxt, a = 2 * a + 1 - type;
    }
    return a - sz;
  }

  template< typename C >
  int find_first(int a, const C &check) {
    Monoid L = M1;
    if(a <= 0) {
      if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);
      return -1;
    }
    int b = sz;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) {
        Monoid nxt = f(L, seg[a]);
        if(check(nxt)) return find_subtree(a, check, L, false);
        L = nxt;
        ++a;
      }
    }
    return -1;
  }

  template< typename C >
  int find_last(int b, const C &check) {
    Monoid R = M1;
    if(b >= sz) {
      if(check(f(seg[1], R))) return find_subtree(1, check, R, true);
      return -1;
    }
    int a = sz;
    for(b += sz; a < b; a >>= 1, b >>= 1) {
      if(b & 1) {
        Monoid nxt = f(seg[--b], R);
        if(check(nxt)) return find_subtree(b, check, R, true);
        R = nxt;
      }
    }
    return -1;
  }
};

int main() {
  int N;
  cin >> N;
  ll ans = 0;
  vector<P> Point(N);
  vector<ll> y;
  for (int i = 0; i < N; i++) {
    cin >> Point[i].F >> Point[i].S;
    y.push_back(Point[i].S);
  }
  sort(y.begin(),y.end());
  y.erase(unique(y.begin(),y.end()),y.end());
  int sz = (int)y.size();
  SegmentTree<ll> Seg1(sz,f,INF);
  SegmentTree<ll> Seg2(sz,f,INF);
  // Seg1 : 点が左にあるとき
  Seg1.build(); Seg2.build();
  sort(Point.begin(),Point.end());
  for (int i = 0; i < N; i++) {
    int ind = lower_bound(y.begin(),y.end(),Point[i].S) - y.begin();
    ll l = Point[i].F + Point[i].S;
    ll r = Point[i].F - Point[i].S;
    ll res1 = Point[i].F - (Seg1.query(0,ind+1) - Point[i].S);
    ll res2 = Point[i].F - (Seg2.query(ind,sz) + Point[i].S);
    ans = max({ans,res1,res2});
    if (Seg1[ind] == INF) {
      Seg1.update(ind,l);
    }
    if (Seg2[ind] == INF) {
      Seg2.update(ind,r);
    }
  }
  cout << ans << endl;
  return 0;
}

Measured memory_bytes: 16392