#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 10;
const long long int INFLL = 1e18 + 10;
const long double EPS = 1e-8;
const long double EPSLD = 1e-14;
const long long int MOD = 1000000007;
template <class T>
T &chmin(T &a, const T &b) {
  return a = min(a, b);
}
template <class T>
T &chmax(T &a, const T &b) {
  return a = max(a, b);
}
struct Unionfind {
  vector<int> size;
  vector<int> par;
  Unionfind() {}
  Unionfind(int n) : size(n, 1), par(n) {
    for (int i = (0); i < (int)(n); i++) par[i] = i;
  }
  void init(int n) {
    size.resize(n);
    par.resize(n);
    for (int i = (0); i < (int)(n); i++) {
      size[i] = 1;
      par[i] = i;
    }
  }
  int find(int x) {
    if (par[x] == x) return x;
    return par[x] = find(par[x]);
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;
    if (size[y] < size[x]) swap(x, y);
    par[x] = y;
    size[y] += size[x];
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y); }
};
vector<long long int> compress(vector<long long int> a) {
  vector<long long int> ord = a, res;
  sort((ord).begin(), (ord).end());
  ord.erase(unique((ord).begin(), (ord).end()), ord.end());
  for (auto &w : a)
    res.emplace_back(lower_bound((ord).begin(), (ord).end(), w) - ord.begin());
  return res;
}
Unionfind uf;
struct Segtree {
  vector<long long int> cnt, an;
  int size;
  void init(int n) {
    size = 1;
    while (size < n) size *= 2;
    cnt = vector<long long int>(size * 2 - 1, 0);
    an = vector<long long int>(size * 2 - 1, -2);
  }
  void add(int k, int id) {
    k += size - 1;
    cnt[k] = 1;
    an[k] = id;
    while (k > 0) {
      k = (k - 1) / 2;
      cnt[k] = cnt[k * 2 + 1] + cnt[k * 2 + 2];
      if (an[k] == -2)
        an[k] = id;
      else
        an[k] = -1;
    }
  }
  void del(int k) {
    k += size - 1;
    cnt[k] = 0;
    an[k] = -2;
    while (k > 0) {
      k = (k - 1) / 2;
      cnt[k] = cnt[k * 2 + 1] + cnt[k * 2 + 2];
      an[k] = -1;
      if (an[k * 2 + 1] == -2 && an[k * 2 + 2] == -2) an[k] = -2;
    }
  }
  long long int query(int a, int b, int id, int k, int l, int r) {
    if (an[k] == -2) return 0;
    if (a <= l && r <= b) {
      if (an[k] != -1) {
        if (uf.same(an[k], id)) return cnt[k];
        uf.unite(an[k], id);
        return cnt[k] - 1;
      }
      an[k] = id;
    } else if (b <= l || r <= a) {
      return 0;
    }
    long long int chl = query(a, b, id, k * 2 + 1, l, (l + r) / 2);
    long long int chr = query(a, b, id, k * 2 + 2, (l + r) / 2, r);
    return chl + chr;
  }
  long long int query(int a, int b, int id) {
    return query(a, b, id, 0, 0, size);
  }
};
const int MAX_N = 200010;
int n;
long long int x1[MAX_N], x2[MAX_N];
long long int z1[MAX_N], z2[MAX_N];
vector<long long int> ix, iy;
vector<long long int> xs, ys;
Segtree seg;
vector<pair<pair<long long int, long long int>,
            pair<long long int, long long int> > >
    qu;
long long int res[MAX_N];
long long int ans;
int main() {
  scanf("%d", &n);
  for (int i = (0); i < (int)(n); i++) {
    scanf("%lld %lld %lld %lld", &x1[i], &z1[i], &x2[i], &z2[i]);
    ix.emplace_back(x1[i]);
    ix.emplace_back(x2[i]);
    iy.emplace_back(z1[i]);
    iy.emplace_back(z2[i]);
  }
  xs = compress(ix);
  ys = compress(iy);
  for (int i = (0); i < (int)(n); i++) {
    if (xs[i * 2] == xs[i * 2 + 1])
      qu.emplace_back(pair<long long int, long long int>(xs[i * 2], ys[i * 2]),
                      pair<long long int, long long int>(ys[i * 2 + 1], i));
    else {
      qu.emplace_back(pair<long long int, long long int>(xs[i * 2], -1),
                      pair<long long int, long long int>(ys[i * 2], i));
      qu.emplace_back(pair<long long int, long long int>(xs[i * 2 + 1], INFLL),
                      pair<long long int, long long int>(ys[i * 2], i));
      res[i] = x2[i] - x1[i];
    }
  }
  sort((qu).begin(), (qu).end());
  uf.init(n);
  seg.init(3 * n);
  for (auto &q : qu) {
    int id = q.second.second;
    if (q.first.second == -1)
      seg.add(q.second.first, id);
    else if (q.first.second == INFLL)
      seg.del(q.second.first);
    else
      res[id] =
          z2[id] - z1[id] - seg.query(q.first.second, q.second.first + 1, id);
  }
  for (int i = (0); i < (int)(n); i++)
    if (uf.find(i) != i) res[uf.find(i)] += res[i];
  for (int i = (0); i < (int)(n); i++)
    if (uf.find(i) == i) chmax(ans, res[i]);
  cout << ans << endl;
  return 0;
}
