#include <bits/stdc++.h>
using namespace std;
bool get(bool a, bool b, pair<bool, bool> form) {
  return (a ^ form.first) | (b ^ form.second);
}
template <typename T>
ostream& operator<<(ostream& out, array<T, 2> a) {
  return out << '[' << a[0] << ' ' << a[1] << ']';
}
template <typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> a) {
  return out << '(' << a.first << ", " << a.second << ')';
}
template <typename T>
ostream& operator<<(ostream& out, vector<T> a) {
  out << '[';
  for (auto i : a) out << i << " ";
  return out << ']';
}
vector<int> dsu;
int find(int i) { return dsu[i] == i ? i : dsu[i] = find(dsu[i]); }
void join(int a, int b) { dsu[find(a)] = find(b); }
struct node {
  node *L, *R;
  int last = 0, horcnt = 0, vcnt = 0;
  int l, r, mid;
  node(int ll, int rr) {
    l = ll, r = rr, mid = l + r >> 1;
    if (l != r) L = new node(l, mid), R = new node(mid + 1, r);
  }
  void updh(int id, int num = 1) {
    horcnt += num;
    if (!id) return;
    if (vcnt && last && id) join(id, last);
    last = id;
  }
  void down() {
    L->updh(last, horcnt), R->updh(last, horcnt), last = horcnt = 0;
  }
  void up() { vcnt = L->vcnt + R->vcnt; }
  int updatehori(int ll, int rr, int id) {
    if (ll > r || rr < l) return 0;
    if (ll <= l && rr >= r) return updh(id), vcnt;
    down();
    return L->updatehori(ll, rr, id) + R->updatehori(ll, rr, id);
  }
  int addvert(int i, int id) {
    if (l == r) {
      last = 0;
      vcnt++;
      return horcnt;
    }
    down();
    int a = (i <= mid ? L : R)->addvert(i, id);
    up();
    return a;
  }
  int remvert(int i, int id) {
    if (l == r) {
      if (last) join(last, id);
      vcnt--;
      return horcnt;
    }
    down();
    int a = (i <= mid ? L : R)->remvert(i, id);
    up();
    return a;
  }
} * root;
vector<int> lis, ans;
vector<int64_t> sizes, tans;
vector<bool> types;
vector<pair<pair<int, pair<int, int>>, pair<int, int>>> evts;
signed main() {
  int n;
  cin >> n;
  ans.resize(n + 1);
  dsu.resize(n + 1);
  iota((dsu).begin(), (dsu).end(), 0);
  types.resize(n + 1);
  sizes.resize(n + 1);
  tans.resize(n + 1);
  int64_t total = 0;
  for (int i = 1; i <= n; i++) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    if (a == c)
      evts.push_back({{b, {0, i}}, {a, a}}),
          evts.push_back({{d, {2, i}}, {c, c}});
    else
      evts.push_back({{b, {1, i}}, {a, c}});
    types[i] = a == c;
    total += (sizes[i] = max(d - b, c - a));
    lis.push_back(a);
    lis.push_back(c);
  }
  sort((lis).begin(), (lis).end());
  lis.erase(unique((lis).begin(), (lis).end()), lis.end());
  root = new node(0, lis.size() - 1);
  sort((evts).begin(), (evts).end());
  for (auto _i : evts) {
    int type = _i.first.second.first, id = _i.first.second.second,
        a = lower_bound((lis).begin(), (lis).end(), _i.second.first) -
            lis.begin(),
        c = (lower_bound((lis).begin(), (lis).end(), _i.second.second) -
             lis.begin());
    if (type == 0) ans[id] = -root->addvert(a, id);
    if (type == 1) ans[id] = root->updatehori(a, c, id);
    if (type == 2) ans[id] += root->remvert(a, id);
  }
  for (int i = 1; i <= n; i++) {
    tans[find(i)] += (ans[i] + 1) - (2 + types[i] * ans[i]);
    if (dsu[i] != i) sizes[find(i)] += sizes[i];
  }
  int64_t maxs = 0;
  for (int i = 1; i <= n; i++)
    if (dsu[i] == i) maxs = max(maxs, sizes[i] - tans[i] - 1);
  cout << maxs << endl;
}
