#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <cstring>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <queue>
#include <utility>
#include <fstream>
using namespace std;
struct event {
    int x,type,y,righty;
};
struct P {
    int right,dsu,number;
};
int xbegin[1000000],compcount,fen[1000000],xend[1000000],ybegin[1000000],yend[1000000],realx[1000000],realy[1000000],parent[1000000];
event events[1000000];
long long ans[1000000],best;
pair <int,int> xx[1000000],yy[1000000];
map <int, P> lefts;
set <int> s;
int v,n;
void event_vertical(int x, int yl, int yr) {
    v++;
    events[v].x=x;
    events[v].type=2;
    events[v].y=yl;
    events[v].righty=yr;
}
void event_horizantal_begin(int x, int y, int xx) {
    v++;
    events[v].x=x;
    events[v].type=1;
    events[v].y=y;
    events[v].righty=xx;
}
void event_horizantal_end(int x, int y) {
    v++;
    events[v].x=x;
    events[v].type=3;
    events[v].y=y;
    events[v].righty=0;
}
bool CMP (const event& i, const event& j) {
    return (i.x<j.x || (i.x==j.x && i.type<j.type));
}
void compressX() {
    for (int i=1;i<=n;i++) xx[i]=make_pair(xbegin[i],i);
    for (int i=1;i<=n;i++) xx[i+n]=make_pair(xend[i],i+n);
    sort(xx+1,xx+2*n+1);
    int v=1;
    xx[0]=make_pair(xx[1].first-1,0);
    for (int i=1;i<=2*n;i++) {
        if (xx[i].first!=xx[i-1].first) v++;
        realx[v]=xx[i].first;
        int t=xx[i].second;
        if (t>n) xend[t-n]=v;
        else xbegin[t]=v;
    }
}
void compressY() {
    for (int i=1;i<=n;i++) yy[i]=make_pair(ybegin[i],i);
    for (int i=1;i<=n;i++) yy[i+n]=make_pair(yend[i],i+n);
    sort(yy+1,yy+2*n+1);
    int v=1;
    yy[0]=make_pair(yy[1].first-1,0);
    for (int i=1;i<=2*n;i++) {
        if (yy[i].first!=yy[i-1].first) v++;
        realy[v]=yy[i].first;
        int t=yy[i].second;
        if (t>n) yend[t-n]=v;
        else ybegin[t]=v;
    }
}
void init() {
    cin >> n;
    for (int i=1;i<=n;i++) cin >> xbegin[i] >> ybegin[i] >> xend[i] >> yend[i];
    compressX();
    compressY();
}
void make_events() {
    v=0;
    for (int i=1;i<=n;i++) {
        if (xbegin[i]==xend[i]) event_vertical(xbegin[i],ybegin[i],yend[i]);
        else {
            event_horizantal_begin(xbegin[i],ybegin[i],xend[i]);
            event_horizantal_end(xend[i],ybegin[i]);
        }
    }
    sort(events+1,events+v+1, CMP);
}
int findsum(int x) {
    int s=0;
    while (x>=1) {
        s+=fen[x];
        x=(x & (x-1));
    }
    return s;
}
void md(int x, int y) {
    while (x<=400010) {
        fen[x]+=y;
        x=(x | (x-1))+1;
    }
}
int findset(int x) {
    if (parent[x]==0) return x;
    parent[x]=findset(parent[x]);
    return parent[x];
}
void divide(int y, int l) {
    set<int>::iterator it2=s.upper_bound(y);
    it2--;
    P cnt=lefts[l];
    if (y>l) {
        int r=*it2;
        int nsize=findsum(r)-findsum(l-1);
        lefts[l].right=r;
        lefts[l].number=nsize;
    } else lefts.erase(l);
    if (y<cnt.right) {
        it2++;
        int nl=*it2;
        int nsize=findsum(cnt.right)-findsum(nl-1);
        lefts[nl].right=cnt.right;
        lefts[nl].dsu=cnt.dsu;
        lefts[nl].number=nsize;
    }
}
int main() {
    ios_base::sync_with_stdio(0);
    init();
    make_events();
    compcount=0;
    best=0;
    s.insert(0);
    s.insert(2000000);
    lefts[2000000]={2000000,0,0};
    lefts[0]={0,0,0};
    for (int i=1;i<=v;i++) {
        if (events[i].type==1) {
            int y=events[i].y;
            compcount++;
            ans[compcount]=realx[events[i].righty]-realx[events[i].x];
            map<int,P>::iterator it1=lefts.upper_bound(y);
            it1--;
            int l=it1->first;
            if (l<=y && y<=lefts[l].right) divide(y,l);
            s.insert(y);
            lefts[y].right=y;
            lefts[y].dsu=compcount;
            lefts[y].number=1;
            md(y,1);
        }
        if (events[i].type==3) {
            int y=events[i].y;
            s.erase(y);
            map<int, P>::iterator it=lefts.upper_bound(y);
            it--;
            md(y,-1);
            int l=it->first;
            if (lefts[l].right==l) lefts.erase(l);
            else
            if (lefts[l].right==y) {
                set<int>::iterator it=s.lower_bound(y);
                it--;
                lefts[l].right=*it;
                lefts[l].number--;
            }
            else
            if (l==y) {
                set<int>::iterator it=s.lower_bound(y);
                P cnt=lefts[l];
                lefts.erase(l);
                lefts[*it]=cnt;
                lefts[*it].number--;
            }
            else lefts[l].number--;
        }
        if (events[i].type==2) {
            int yl=events[i].y;
            int yr=events[i].righty;
            if (realy[yr]-realy[yl]>best) best=realy[yr]-realy[yl];
            if (findsum(yr)-findsum(yl-1)==0) continue;
            int nDSU=0;
            int nl=0;
            int nr=0;
            int dif=1;
            map<int, P>::iterator it=lefts.lower_bound(yl);
            it--;
            int l=it->first;
            P cnt=lefts[l];
            if (cnt.right>=yl && l<=yl) {
                nl=l;
                nr=cnt.right;
                nDSU=findset(cnt.dsu);
                lefts.erase(l);
            }
            while (true) {
                map<int, P>::iterator it1=lefts.lower_bound(yl);
                int l=it1->first;
                if (l>yr) break;
                if (lefts[l].right>yr) break;
                if (nl==0) nl=l;
                P cnt=lefts[l];
                nr=cnt.right;
                if (nDSU==0) nDSU=findset(cnt.dsu);
                else
                if (nDSU!=findset(cnt.dsu)) {
                    ans[nDSU]+=ans[findset(cnt.dsu)];
                    parent[findset(cnt.dsu)]=nDSU;
                    dif++;
                }
                lefts.erase(l);
            }
            it=lefts.upper_bound(yr);
            it--;
            l=it->first;
            cnt=lefts[l];
            if (cnt.right>=yr && l<=yr) {
                if (nl==0) nl=l;
                nr=cnt.right;
                if (nDSU==0) nDSU=findset(cnt.dsu);
                else
                if (nDSU!=findset(cnt.dsu)) {
                    ans[nDSU]+=ans[findset(cnt.dsu)];
                    parent[findset(cnt.dsu)]=nDSU;
                    dif++;
                }
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
                ans[nDSU]+=realy[yr]-realy[yl]-(findsum(yr)-findsum(yl-1)-1)+dif-1;
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define left son[0]
#define right son[1]

struct Seg
{
       int fx, fy, tx, ty, number;
       Seg () {}
       Seg (int _fx, int _fy, int _tx, int _ty, int _number) :
           fx(_fx), fy(_fy), tx(_tx), ty(_ty), number(_number) {}
}      a[200050], h[200050], v[200050], hh[200050], vv[200050], doing[200050];

struct ST
{
       int size;
       pair <int, int> p;
       ST *father, *son[2];
       ST () {}
       ST (ST *F, int S, pair <int, int> P)
       {
          father = F;
          size = S;
          p = P;
          left = right = 0;
          return;
       }
}      *rt, stree[10000050];

struct Tedge
{
       int to, flag, next;
}      edge[1000050], mem[1000050];

struct Tree1
{
       int f, down;
}      tree1[10000050];

int now, sf, nx, ny, nnx, nny, group, vs, ss, first[1000050], last[1000050], up[1000050], scale[1000050];
int x[1000050], y[1000050], xx[1000050], yy[1000050], father[200050];
int belong[200050], need[1000050];
bool firsttime, vis[1000050];
vector <int> tree[4000050];
long long result;
map <pair <int, int>, bool> f;

int Rand()
{
    return (rand() << 15) | rand();
}

void Addedge(int x, int y, int flag)
{
     edge[++now].to = y;
     edge[now].flag = flag;
     edge[now].next = first[x];
     first[x] = now;

     return;
}

void Addedges(int x, int y, int flag)
{
     mem[++sf].to = y;
     mem[sf].flag = flag;
     mem[sf].next = last[x];
     last[x] = sf;

     return;
}

int  Halfx(int ask)
{
int  low, mid, high;

     low = 0;
     high = nx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (xx[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Halfy(int ask)
{
int  low, mid, high;

     low = 0;
     high = ny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (yy[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Father(int current)
{
     if  (father[current] != current)
     {
         father[current] = Father(father[current]);
     }

     return father[current];
}

void Down1(int root)
{
     if  (tree1[root].down != 0)
     {
         if  (tree1[root].f == 0)
         {
             tree1[root].down = 0;
             return;
         }
         father[Father(tree1[root].f)] = Father(tree1[root].down);
         if  (tree1[root << 1].down != 0)
         {
             if  (tree1[root << 1].f != 0)
             {
                 father[Father(tree1[root << 1].down)] = Father(tree1[root].down);
             }
         }
         if  (tree1[(root << 1) | 1].down != 0)
         {
             if  (tree1[(root << 1) | 1].f != 0)
             {
                 father[Father(tree1[(root << 1) | 1].down)] = Father(tree1[root].down);
             }
         }
         tree1[root << 1].down = tree1[root].down;
         tree1[(root << 1) | 1].down = tree1[root].down;
         tree1[root].down = 0;
     }

     return;
}

void Force1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         tree1[root].f = news;
         return;
     }
     Force1(root << 1, nowleft, mid, askleft, askright, news);
     Force1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

void Update1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         if  (tree1[root].f != 0)
         {
             tree1[root].down = news;
             Down1(root);
         }
         return;
     }
     Update1(root << 1, nowleft, mid, askleft, askright, news);
     Update1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

int  Ask1(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return 0;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return Father(tree1[root].f);
     }

     return max(Ask1(root << 1, nowleft, mid, askleft, askright),
                Ask1((root << 1) | 1, mid + 1, nowright, askleft, askright));
}

int  X(int ask)
{
int  low, mid, high;

     low = 0;
     high = nnx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (x[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Y(int ask)
{
int  low, mid, high;

     low = 0;
     high = nny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (y[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

// stree

void UST(ST *current)
{
     current -> size = 1;
     if  (current -> left)
     {
         current -> size += current -> left -> size;
     }
     if  (current -> right)
     {
         current -> size += current -> right -> size;
     }

     return;
}

void Rotate(ST *current, int flag)
{
     current -> father -> son[flag ^ 1] = current -> son[flag];
     if  (current -> son[flag])
     {
         current -> son[flag] -> father = current -> father;
     }
     current -> son[flag] = current -> father;
     if  (current -> father -> father)
     {
         current -> father -> father ->
         son[current -> father -> father -> left != current -> father] = current;
     }
     current -> father = current -> father -> father;
     current -> son[flag] -> father = current;
     UST(current -> son[flag]);

     return;
}

void Splay(ST *current, ST *target)
{
     while (current -> father != target)
     {
           if  (current -> father -> father == target)
           {
               Rotate(current, current -> father -> right != current);
           }   else
           if  (current -> father -> father -> left == current -> father &&
               current -> father -> left == current)
           {
               Rotate(current -> father, 1);
               Rotate(current, 1);
           }   else
           if  (current -> father -> father -> right == current -> father &&
               current -> father -> right == current)
           {
               Rotate(current -> father, 0);
               Rotate(current, 0);
           }   else
           {
               Rotate(current, current -> father -> right != current);
               Rotate(current, current -> father -> right != current);
           }
     }
     UST(current);
     if  (!target)
     {
         rt = current;
     }

     return;
}

void Find(int ask, ST *target)
{
ST   *current = rt;

     while (current)
     {
           if  (current -> left)
           {
               if  (ask == current -> left -> size + 1)
               {
                   break;
               }
           }   else
           if  (ask == 1)
           {
               break;
           }
           if  (current -> left && ask < current -> left -> size + 1)
           {
               current = current -> left;
           }   else
           {
               ask--;
               if  (current -> left)
               {
                   ask -= current -> left -> size;
               }
               current = current -> right;
           }
     }
     Splay(current, target);

     return;

     return;
}

void Insert(pair <int, int> ask)
{
ST   *current = rt;

     while (current)
     {
           if  (ask < current -> p)
           {
               if  (current -> left)
               {
                   current = current -> left;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> left = &stree[vs];
                   Splay(current -> left, 0);
                   return;
               }
           }   else
           {
               if  (current -> right)
               {
                   current = current -> right;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> right = &stree[vs];
                   Splay(current -> right, 0);
                   return;
               }
           }
     }

     return;
}

int  Findkth(pair <int, int> ask)
{
ST   *current = rt, *best = rt;

     while (current)
     {
           if  (ask <= current -> p)
           {
               best = current;
               current = current -> left;
           }   else
           {
               current = current -> right;
           }
     }
     Splay(best, 0);
     if  (rt -> left)
     {
         return rt -> left -> size + 1;
     }
     return 1;
}

// stree

int  Up(int current)
{
     if  (up[current] != current)
     {
         up[current] = Up(up[current]);
     }

     return up[current];
}

void Clear(int root, int nowleft, int nowright)
{
int  mid = (nowleft + nowright) >> 1;

     tree[root].clear();
     if  (nowleft == nowright)
     {
         return;
     }
     Clear(root << 1, nowleft, mid);
     Clear((root << 1) | 1, mid + 1, nowright);

     return;
}

void Force(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     tree[root].push_back(news);
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Force(root << 1, nowleft, mid, askleft, askright, news);
     Force((root << 1) | 1, mid + 1, nowright, askleft, askright, news);

     return;
}

void Update(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1, one, two, next, temp, i, rank, ss;
ST  *die;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         temp = tree[root].size();
         if  (temp == 0)
         {
             return;
         }

         for (ss = i = 0; i < temp; i++)
         {
             next = Up(tree[root][i]);
             if  (!vis[next])
             {
                 vis[next] = true;
                 need[++ss] = next;
             }
         }

         for (i = 1; i <= ss; i++)
         {
             vis[need[i]] = false;
             next = need[i];
             one = Findkth(make_pair(next, nowleft));
             two = Findkth(make_pair(next, nowright + 1));
             result += two - one;
             if  (firsttime)
             {
                 result--;
                 group = next;
                 firsttime = false;
                 continue;
             }
             if  (group == next)
             {
                 continue;
             }
             result--;
             if  (scale[group] < scale[next])
             {
                 swap(group, next);
             }
             scale[group] += scale[next];
             up[next] = group;
             while (true)
             {
                   rank = Findkth(make_pair(next, -999999999));
                   die = rt;
                   if  (die -> p.first != next)
                   {
                       break;
                   }
                   Find(rank - 1, 0);
                   Find(rank + 1, rt);
                   rt -> right -> left = 0;
                   UST(rt -> right);
                   UST(rt);
                   Insert(make_pair(group, die -> p.second));
             }
         }
         tree[root].clear();
         tree[root].push_back(group);
         return;
     }
     Update(root << 1, nowleft, mid, askleft, askright);
     Update((root << 1) | 1, mid + 1, nowright, askleft, askright);

     return;
}

long long Solve(int total)
{
int  nh, nv, i, j, ts, temp, pointer, next, flag, l, r, a, b, p, q, ad, one, two, rank;
long long all;
map <pair <int, int>, bool>::iterator it;

     nh = nv = nnx = nny = all = result = 0;
     for (i = 1; i <= total; i++)
     {
         x[++nnx] = doing[i].fx;
         x[++nnx] = doing[i].tx;
         y[++nny] = doing[i].fy;
         y[++nny] = doing[i].ty;
         if  (doing[i].fx != doing[i].tx)
         {
             hh[++nh] = doing[i];
         }   else
         {
             vv[++nv] = doing[i];
         }
         all += doing[i].tx - doing[i].fx +
                doing[i].ty - doing[i].fy;
     }

     for (i = 1; i <= nh; i++)
     {
         up[i] = i;
         scale[i] = 1;
     }

     sort(x + 1, x + nnx + 1);

     for (i = j = 1; i < nnx; i++)
     if  (x[i + 1] != x[j])
     {
         x[++j] = x[i + 1];
     }
     nnx = j;

     sort(y + 1, y + nny + 1);

     for (i = j = 1; i < nny; i++)
     if  (y[i + 1] != y[j])
     {
         y[++j] = y[i + 1];
     }
     nny = j;

     memset(last, 0, 4 * nnx + 4);
     sf = 0;

     for (i = 1; i <= nh; i++)
     {
         Addedges(X(hh[i].fx), i, 0);
         Addedges(X(hh[i].tx), i, 2);
     }
     for (i = 1; i <= nv; i++)
     {
         Addedges(X(vv[i].fx), i, 1);
     }

     Clear(1, 1, nny);

     vs = 0;
     stree[++vs] = ST(0, 2, make_pair(-999999999, -999999999));
     rt = &stree[vs];
     stree[++vs] = ST(rt, 1, make_pair(999999999, 999999999));
     rt -> right = &stree[vs];

     for (i = 1; i <= nnx; i++)
     {
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 0)
             {
                 continue;
             }
             ad = Y(hh[next].fy);
             Force(1, 1, nny, ad, ad, next);
             Insert(make_pair(next, ad));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 1)
             {
                 continue;
             }
             firsttime = true;
             Update(1, 1, nny, Y(vv[next].fy), Y(vv[next].ty));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 2)
             {
                 continue;
             }
             rank = Findkth(make_pair(Up(next), Y(hh[next].fy)));
             Find(rank - 1, 0);
             Find(rank + 1, rt);
             rt -> right -> left = 0;
             UST(rt -> right);
             UST(rt);
         }
     }

     return all - result;
}

int main()
{
int nh, nv, n, i, j, fx, fy, tx, ty, total, pointer, next, flag, temp;
long long answer;

//    freopen("e.in", "r", stdin);
//    freopen("e.out", "w", stdout);

    srand((unsigned) time (0));

    nx = ny = nh = nv = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d%d%d", &fx, &fy, &tx, &ty);
        xx[++nx] = fx;
        xx[++nx] = tx;
        yy[++ny] = fy;
        yy[++ny] = ty;
        a[i] = Seg(fx, fy, tx, ty, i);
        if  (fx != tx)
        {
            h[++nh] = Seg(fx, fy, tx, ty, i);
        }   else
        {
            v[++nv] = Seg(fx, fy, tx, ty, i);
        }
    }

    sort(xx + 1, xx + nx + 1);
    for (i = j = 1; i < nx; i++)
    if  (xx[i + 1] != xx[j])
    {
        xx[++j] = xx[i + 1];
    }
    nx = j;

    sort(yy + 1, yy + ny + 1);
    for (i = j = 1; i < ny; i++)
    if  (yy[i + 1] != yy[j])
    {
        yy[++j] = yy[i + 1];
    }
    ny = j;

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= nh; i++)
    {
        Addedge(Halfx(h[i].fx), h[i].number, 0);
        Addedge(Halfx(h[i].tx), h[i].number, 2);
    }
    for (i = 1; i <= nv; i++)
    {
        Addedge(Halfx(v[i].fx), v[i].number, 1);
    }

    for (i = 1; i <= n; i++)
    {
        father[i] = i;
    }
    memset(tree1, 0, sizeof(tree1));
    for (i = 1; i <= nx; i++)
    {
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 0)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            Force1(1, 1, ny, temp, temp, next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 1)
            {
                continue;
            }
            Update1(1, 1, ny, Halfy(a[next].fy), Halfy(a[next].ty), next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 2)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            belong[next] = Ask1(1, 1, ny, temp, temp);
            Force1(1, 1, ny, temp, temp, 0);
        }
    }
    for (i = 1; i <= nv; i++)
    {
        belong[v[i].number] = Father(v[i].number);
    }
    for (i = 1; i <= n; i++)
    {
        belong[i] = Father(belong[i]);
    }

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= n; i++)
    {
        Addedge(belong[i], i, 0);
    }
    answer = 0;
    for (i = 1; i <= n; i++)
    {
        total = 0;
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            doing[++total] = a[next];
        }
        if  (total == 0)
        {
            continue;
        }
        answer = max(answer, Solve(total));
    }

    printf("%I64d\n", answer);

    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define left son[0]
#define right son[1]

struct Seg
{
       int fx, fy, tx, ty, number;
       Seg () {}
       Seg (int _fx, int _fy, int _tx, int _ty, int _number) :
           fx(_fx), fy(_fy), tx(_tx), ty(_ty), number(_number) {}
}      a[200050], h[200050], v[200050], hh[200050], vv[200050], doing[200050];

struct ST
{
       int size;
       pair <int, int> p;
       ST *father, *son[2];
       ST () {}
       ST (ST *F, int S, pair <int, int> P)
       {
          father = F;
          size = S;
          p = P;
          left = right = 0;
          return;
       }
}      *rt, stree[10000050];

struct Tedge
{
       int to, flag, next;
}      edge[1000050], mem[1000050];

struct Tree1
{
       int f, down;
}      tree1[10000050];

int now, sf, nx, ny, nnx, nny, group, vs, first[1000050], last[1000050], up[1000050], scale[1000050];
int x[1000050], y[1000050], xx[1000050], yy[1000050], father[200050];
int belong[200050], need[1000050], delta[1000050];
bool firsttime, vis[1000050];
vector <int> tree[4000050];
long long result;

int Rand()
{
    return (rand() << 15) | rand();
}

void Addedge(int x, int y, int flag)
{
     edge[++now].to = y;
     edge[now].flag = flag;
     edge[now].next = first[x];
     first[x] = now;

     return;
}

void Addedges(int x, int y, int flag)
{
     mem[++sf].to = y;
     mem[sf].flag = flag;
     mem[sf].next = last[x];
     last[x] = sf;

     return;
}

int  Halfx(int ask)
{
int  low, mid, high;

     low = 0;
     high = nx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (xx[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Halfy(int ask)
{
int  low, mid, high;

     low = 0;
     high = ny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (yy[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Father(int current)
{
     if  (father[current] != current)
     {
         father[current] = Father(father[current]);
     }

     return father[current];
}

void Down1(int root)
{
     if  (tree1[root].down != 0)
     {
         if  (tree1[root].f == 0)
         {
             tree1[root].down = 0;
             return;
         }
         father[Father(tree1[root].f)] = Father(tree1[root].down);
         if  (tree1[root << 1].down != 0)
         {
             if  (tree1[root << 1].f != 0)
             {
                 father[Father(tree1[root << 1].down)] = Father(tree1[root].down);
             }
         }
         if  (tree1[(root << 1) | 1].down != 0)
         {
             if  (tree1[(root << 1) | 1].f != 0)
             {
                 father[Father(tree1[(root << 1) | 1].down)] = Father(tree1[root].down);
             }
         }
         tree1[root << 1].down = tree1[root].down;
         tree1[(root << 1) | 1].down = tree1[root].down;
         tree1[root].down = 0;
     }

     return;
}

void Force1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         tree1[root].f = news;
         return;
     }
     Force1(root << 1, nowleft, mid, askleft, askright, news);
     Force1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

void Update1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         if  (tree1[root].f != 0)
         {
             tree1[root].down = news;
             Down1(root);
         }
         return;
     }
     Update1(root << 1, nowleft, mid, askleft, askright, news);
     Update1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

int  Ask1(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return 0;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return Father(tree1[root].f);
     }

     return max(Ask1(root << 1, nowleft, mid, askleft, askright),
                Ask1((root << 1) | 1, mid + 1, nowright, askleft, askright));
}

int  X(int ask)
{
int  low, mid, high;

     low = 0;
     high = nnx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (x[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Y(int ask)
{
int  low, mid, high;

     low = 0;
     high = nny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (y[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

// stree

void UST(ST *current)
{
     current -> size = 1;
     if  (current -> left)
     {
         current -> size += current -> left -> size;
     }
     if  (current -> right)
     {
         current -> size += current -> right -> size;
     }

     return;
}

void Rotate(ST *current, int flag)
{
     current -> father -> son[flag ^ 1] = current -> son[flag];
     if  (current -> son[flag])
     {
         current -> son[flag] -> father = current -> father;
     }
     current -> son[flag] = current -> father;
     if  (current -> father -> father)
     {
         current -> father -> father ->
         son[current -> father -> father -> left != current -> father] = current;
     }
     current -> father = current -> father -> father;
     current -> son[flag] -> father = current;
     UST(current -> son[flag]);

     return;
}

void Splay(ST *current, ST *target)
{
     while (current -> father != target)
     {
           if  (current -> father -> father == target)
           {
               Rotate(current, current -> father -> right != current);
           }   else
           if  (current -> father -> father -> left == current -> father &&
               current -> father -> left == current)
           {
               Rotate(current -> father, 1);
               Rotate(current, 1);
           }   else
           if  (current -> father -> father -> right == current -> father &&
               current -> father -> right == current)
           {
               Rotate(current -> father, 0);
               Rotate(current, 0);
           }   else
           {
               Rotate(current, current -> father -> right != current);
               Rotate(current, current -> father -> right != current);
           }
     }
     UST(current);
     if  (!target)
     {
         rt = current;
     }

     return;
}

void Find(int ask, ST *target)
{
ST   *current = rt;

     while (current)
     {
           if  (current -> left)
           {
               if  (ask == current -> left -> size + 1)
               {
                   break;
               }
           }   else
           if  (ask == 1)
           {
               break;
           }
           if  (current -> left && ask < current -> left -> size + 1)
           {
               current = current -> left;
           }   else
           {
               ask--;
               if  (current -> left)
               {
                   ask -= current -> left -> size;
               }
               current = current -> right;
           }
     }
     Splay(current, target);

     return;

     return;
}

void Insert(pair <int, int> ask)
{
ST   *current = rt;

     while (current)
     {
           if  (ask < current -> p)
           {
               if  (current -> left)
               {
                   current = current -> left;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> left = &stree[vs];
                   Splay(current -> left, 0);
                   return;
               }
           }   else
           {
               if  (current -> right)
               {
                   current = current -> right;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> right = &stree[vs];
                   Splay(current -> right, 0);
                   return;
               }
           }
     }

     return;
}

int  Findkth(pair <int, int> ask)
{
ST   *current = rt, *best = rt;

     while (current)
     {
           if  (ask <= current -> p)
           {
               best = current;
               current = current -> left;
           }   else
           {
               current = current -> right;
           }
     }
     Splay(best, 0);
     if  (rt -> left)
     {
         return rt -> left -> size + 1;
     }
     return 1;
}

// stree

int  Up(int current)
{
     if  (up[current] != current)
     {
         up[current] = Up(up[current]);
     }

     return up[current];
}

void Clear(int root, int nowleft, int nowright)
{
int  mid = (nowleft + nowright) >> 1;

     tree[root].clear();
     if  (nowleft == nowright)
     {
         return;
     }
     Clear(root << 1, nowleft, mid);
     Clear((root << 1) | 1, mid + 1, nowright);

     return;
}

void Force(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     tree[root].push_back(news);
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Force(root << 1, nowleft, mid, askleft, askright, news);
     Force((root << 1) | 1, mid + 1, nowright, askleft, askright, news);

     return;
}

void Update(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1, one, two, next, temp, i, rank, ss;
ST   *die;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         temp = tree[root].size();
         if  (temp == 0)
         {
             return;
         }

         for (ss = i = 0; i < temp; i++)
         {
             next = Up(tree[root][i]);
             if  (!vis[next])
             {
                 vis[next] = true;
                 need[++ss] = next;
                 delta[ss] = Findkth(make_pair(next, nowright + 1)) -
                             Findkth(make_pair(next, nowleft));
             }
         }

         for (i = 1; i <= ss; i++)
         {
             vis[need[i]] = false;
             next = Up(need[i]);
             result += delta[i];
             if  (firsttime)
             {
                 result--;
                 group = next;
                 firsttime = false;
                 continue;
             }
             if  (group == next)
             {
                 continue;
             }
             result--;
             if  (scale[group] < scale[next])
             {
                 swap(group, next);
             }
             scale[group] += scale[next];
             up[next] = group;
             while (true)
             {
                   rank = Findkth(make_pair(next, -999999999));
                   die = rt;
                   if  (die -> p.first != next)
                   {
                       break;
                   }
                   Find(rank - 1, 0);
                   Find(rank + 1, rt);
                   rt -> right -> left = 0;
                   UST(rt -> right);
                   UST(rt);
                   Insert(make_pair(group, die -> p.second));
             }
         }
         tree[root].clear();
         tree[root].push_back(group);
         return;
     }
     Update(root << 1, nowleft, mid, askleft, askright);
     Update((root << 1) | 1, mid + 1, nowright, askleft, askright);

     return;
}

long long Solve(int total)
{
int  nh, nv, i, j, ts, temp, pointer, next, flag, l, r, a, b, p, q, ad, one, two, rank;
long long all;
map <pair <int, int>, bool>::iterator it;

     nh = nv = nnx = nny = all = result = 0;
     for (i = 1; i <= total; i++)
     {
         x[++nnx] = doing[i].fx;
         x[++nnx] = doing[i].tx;
         y[++nny] = doing[i].fy;
         y[++nny] = doing[i].ty;
         if  (doing[i].fx != doing[i].tx)
         {
             hh[++nh] = doing[i];
         }   else
         {
             vv[++nv] = doing[i];
         }
         all += doing[i].tx - doing[i].fx +
                doing[i].ty - doing[i].fy;
     }

     for (i = 1; i <= nh; i++)
     {
         up[i] = i;
         scale[i] = 1;
     }

     sort(x + 1, x + nnx + 1);

     for (i = j = 1; i < nnx; i++)
     if  (x[i + 1] != x[j])
     {
         x[++j] = x[i + 1];
     }
     nnx = j;

     sort(y + 1, y + nny + 1);

     for (i = j = 1; i < nny; i++)
     if  (y[i + 1] != y[j])
     {
         y[++j] = y[i + 1];
     }
     nny = j;

     memset(last, 0, 4 * nnx + 4);
     sf = 0;

     for (i = 1; i <= nh; i++)
     {
         Addedges(X(hh[i].fx), i, 0);
         Addedges(X(hh[i].tx), i, 2);
     }
     for (i = 1; i <= nv; i++)
     {
         Addedges(X(vv[i].fx), i, 1);
     }

     Clear(1, 1, nny);

     vs = 0;
     stree[++vs] = ST(0, 2, make_pair(-999999999, -999999999));
     rt = &stree[vs];
     stree[++vs] = ST(rt, 1, make_pair(999999999, 999999999));
     rt -> right = &stree[vs];

     for (i = 1; i <= nnx; i++)
     {
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 0)
             {
                 continue;
             }
             ad = Y(hh[next].fy);
             Force(1, 1, nny, ad, ad, next);
             Insert(make_pair(next, ad));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 1)
             {
                 continue;
             }
             firsttime = true;
             Update(1, 1, nny, Y(vv[next].fy), Y(vv[next].ty));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 2)
             {
                 continue;
             }
             rank = Findkth(make_pair(Up(next), Y(hh[next].fy)));
             Find(rank - 1, 0);
             Find(rank + 1, rt);
             rt -> right -> left = 0;
             UST(rt -> right);
             UST(rt);
         }
     }

     return all - result;
}

int main()
{
int nh, nv, n, i, j, fx, fy, tx, ty, total, pointer, next, flag, temp;
long long answer;

//    freopen("e.in", "r", stdin);
//    freopen("e.out", "w", stdout);

    srand((unsigned) time (0));

    nx = ny = nh = nv = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d%d%d", &fx, &fy, &tx, &ty);
        xx[++nx] = fx;
        xx[++nx] = tx;
        yy[++ny] = fy;
        yy[++ny] = ty;
        a[i] = Seg(fx, fy, tx, ty, i);
        if  (fx != tx)
        {
            h[++nh] = Seg(fx, fy, tx, ty, i);
        }   else
        {
            v[++nv] = Seg(fx, fy, tx, ty, i);
        }
    }

    sort(xx + 1, xx + nx + 1);
    for (i = j = 1; i < nx; i++)
    if  (xx[i + 1] != xx[j])
    {
        xx[++j] = xx[i + 1];
    }
    nx = j;

    sort(yy + 1, yy + ny + 1);
    for (i = j = 1; i < ny; i++)
    if  (yy[i + 1] != yy[j])
    {
        yy[++j] = yy[i + 1];
    }
    ny = j;

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= nh; i++)
    {
        Addedge(Halfx(h[i].fx), h[i].number, 0);
        Addedge(Halfx(h[i].tx), h[i].number, 2);
    }
    for (i = 1; i <= nv; i++)
    {
        Addedge(Halfx(v[i].fx), v[i].number, 1);
    }

    for (i = 1; i <= n; i++)
    {
        father[i] = i;
    }
    memset(tree1, 0, sizeof(tree1));
    for (i = 1; i <= nx; i++)
    {
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 0)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            Force1(1, 1, ny, temp, temp, next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 1)
            {
                continue;
            }
            Update1(1, 1, ny, Halfy(a[next].fy), Halfy(a[next].ty), next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 2)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            belong[next] = Ask1(1, 1, ny, temp, temp);
            Force1(1, 1, ny, temp, temp, 0);
        }
    }
    for (i = 1; i <= nv; i++)
    {
        belong[v[i].number] = Father(v[i].number);
    }
    for (i = 1; i <= n; i++)
    {
        belong[i] = Father(belong[i]);
    }

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= n; i++)
    {
        Addedge(belong[i], i, 0);
    }
    answer = 0;
    for (i = 1; i <= n; i++)
    {
        total = 0;
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            doing[++total] = a[next];
        }
        if  (total == 0)
        {
            continue;
        }
        answer = max(answer, Solve(total));
    }

    printf("%I64d\n", answer);

    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define left son[0]
#define right son[1]

struct Seg
{
       int fx, fy, tx, ty, number;
       Seg () {}
       Seg (int _fx, int _fy, int _tx, int _ty, int _number) :
           fx(_fx), fy(_fy), tx(_tx), ty(_ty), number(_number) {}
}      a[200050], h[200050], v[200050], hh[200050], vv[200050], doing[200050];

struct ST
{
       int size;
       pair <int, int> p;
       ST *father, *son[2];
       ST () {}
       ST (ST *F, int S, pair <int, int> P)
       {
          father = F;
          size = S;
          p = P;
          left = right = 0;
          return;
       }
}      *rt, stree[10000050];

struct Tedge
{
       int to, flag, next;
}      edge[1000050], mem[1000050];

struct Tree1
{
       int f, down;
}      tree1[10000050];

int now, sf, nx, ny, nnx, nny, group, vs, ss, first[1000050], last[1000050], up[1000050], scale[1000050];
int x[1000050], y[1000050], xx[1000050], yy[1000050], father[200050];
int belong[200050], need[1000050];
bool firsttime, vis[1000050];
vector <int> tree[4000050];
long long result;
pair <int, int> add[1000050];

int Rand()
{
    return (rand() << 15) | rand();
}

void Addedge(int x, int y, int flag)
{
     edge[++now].to = y;
     edge[now].flag = flag;
     edge[now].next = first[x];
     first[x] = now;

     return;
}

void Addedges(int x, int y, int flag)
{
     mem[++sf].to = y;
     mem[sf].flag = flag;
     mem[sf].next = last[x];
     last[x] = sf;

     return;
}

int  Halfx(int ask)
{
int  low, mid, high;

     low = 0;
     high = nx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (xx[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Halfy(int ask)
{
int  low, mid, high;

     low = 0;
     high = ny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (yy[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Father(int current)
{
     if  (father[current] != current)
     {
         father[current] = Father(father[current]);
     }

     return father[current];
}

void Down1(int root)
{
     if  (tree1[root].down != 0)
     {
         if  (tree1[root].f == 0)
         {
             tree1[root].down = 0;
             return;
         }
         father[Father(tree1[root].f)] = Father(tree1[root].down);
         if  (tree1[root << 1].down != 0)
         {
             if  (tree1[root << 1].f != 0)
             {
                 father[Father(tree1[root << 1].down)] = Father(tree1[root].down);
             }
         }
         if  (tree1[(root << 1) | 1].down != 0)
         {
             if  (tree1[(root << 1) | 1].f != 0)
             {
                 father[Father(tree1[(root << 1) | 1].down)] = Father(tree1[root].down);
             }
         }
         tree1[root << 1].down = tree1[root].down;
         tree1[(root << 1) | 1].down = tree1[root].down;
         tree1[root].down = 0;
     }

     return;
}

void Force1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         tree1[root].f = news;
         return;
     }
     Force1(root << 1, nowleft, mid, askleft, askright, news);
     Force1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

void Update1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         if  (tree1[root].f != 0)
         {
             tree1[root].down = news;
             Down1(root);
         }
         return;
     }
     Update1(root << 1, nowleft, mid, askleft, askright, news);
     Update1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

int  Ask1(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return 0;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return Father(tree1[root].f);
     }

     return max(Ask1(root << 1, nowleft, mid, askleft, askright),
                Ask1((root << 1) | 1, mid + 1, nowright, askleft, askright));
}

int  X(int ask)
{
int  low, mid, high;

     low = 0;
     high = nnx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (x[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Y(int ask)
{
int  low, mid, high;

     low = 0;
     high = nny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (y[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

// stree

void UST(ST *current)
{
     current -> size = 1;
     if  (current -> left)
     {
         current -> size += current -> left -> size;
     }
     if  (current -> right)
     {
         current -> size += current -> right -> size;
     }

     return;
}

void Rotate(ST *current, int flag)
{
     current -> father -> son[flag ^ 1] = current -> son[flag];
     if  (current -> son[flag])
     {
         current -> son[flag] -> father = current -> father;
     }
     current -> son[flag] = current -> father;
     if  (current -> father -> father)
     {
         current -> father -> father ->
         son[current -> father -> father -> left != current -> father] = current;
     }
     current -> father = current -> father -> father;
     current -> son[flag] -> father = current;
     UST(current -> son[flag]);

     return;
}

void Splay(ST *current, ST *target)
{
     while (current -> father != target)
     {
           if  (current -> father -> father == target)
           {
               Rotate(current, current -> father -> right != current);
           }   else
           if  (current -> father -> father -> left == current -> father &&
               current -> father -> left == current)
           {
               Rotate(current -> father, 1);
               Rotate(current, 1);
           }   else
           if  (current -> father -> father -> right == current -> father &&
               current -> father -> right == current)
           {
               Rotate(current -> father, 0);
               Rotate(current, 0);
           }   else
           {
               Rotate(current, current -> father -> right != current);
               Rotate(current, current -> father -> right != current);
           }
     }
     UST(current);
     if  (!target)
     {
         rt = current;
     }

     return;
}

void Find(int ask, ST *target)
{
ST   *current = rt;

     while (current)
     {
           if  (current -> left)
           {
               if  (ask == current -> left -> size + 1)
               {
                   break;
               }
           }   else
           if  (ask == 1)
           {
               break;
           }
           if  (current -> left && ask < current -> left -> size + 1)
           {
               current = current -> left;
           }   else
           {
               ask--;
               if  (current -> left)
               {
                   ask -= current -> left -> size;
               }
               current = current -> right;
           }
     }
     Splay(current, target);

     return;

     return;
}

void Insert(pair <int, int> ask)
{
ST   *current = rt;

     while (current)
     {
           if  (ask < current -> p)
           {
               if  (current -> left)
               {
                   current = current -> left;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> left = &stree[vs];
                   Splay(current -> left, 0);
                   return;
               }
           }   else
           {
               if  (current -> right)
               {
                   current = current -> right;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> right = &stree[vs];
                   Splay(current -> right, 0);
                   return;
               }
           }
     }

     return;
}

int  Findkth(pair <int, int> ask)
{
ST   *current = rt, *best = rt;

     while (current)
     {
           if  (ask <= current -> p)
           {
               best = current;
               current = current -> left;
           }   else
           {
               current = current -> right;
           }
     }
     Splay(best, 0);
     if  (rt -> left)
     {
         return rt -> left -> size + 1;
     }
     return 1;
}

// stree

int  Up(int current)
{
     if  (up[current] != current)
     {
         up[current] = Up(up[current]);
     }

     return up[current];
}

void Clear(int root, int nowleft, int nowright)
{
int  mid = (nowleft + nowright) >> 1;

     tree[root].clear();
     if  (nowleft == nowright)
     {
         return;
     }
     Clear(root << 1, nowleft, mid);
     Clear((root << 1) | 1, mid + 1, nowright);

     return;
}

void Force(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     tree[root].push_back(news);
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Force(root << 1, nowleft, mid, askleft, askright, news);
     Force((root << 1) | 1, mid + 1, nowright, askleft, askright, news);

     return;
}

void Update(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1, one, two, next, temp, i, rank, ss, adds;
ST  *die;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         temp = tree[root].size();
         if  (temp == 0)
         {
             return;
         }

         for (adds = ss = i = 0; i < temp; i++)
         {
             next = Up(tree[root][i]);
             if  (!vis[next])
             {
                 vis[next] = true;
                 need[++ss] = next;
             }
         }

         for (i = 1; i <= ss; i++)
         {
             vis[need[i]] = false;
             next = need[i];
             one = Findkth(make_pair(next, nowleft));
             two = Findkth(make_pair(next, nowright + 1));
             if  (one >= two)
             {
                 continue;
             }
             result += two - one;
             if  (firsttime)
             {
                 result--;
                 group = next;
                 firsttime = false;
                 continue;
             }
             if  (group == next)
             {
                 continue;
             }
             result--;
             if  (scale[group] < scale[next])
             {
                 swap(group, next);
             }
             scale[group] += scale[next];
             up[next] = group;
             while (true)
             {
                   rank = Findkth(make_pair(next, -999999999));
                   die = rt;
                   if  (die -> p.first != next)
                   {
                       break;
                   }
                   Find(rank - 1, 0);
                   Find(rank + 1, rt);
                   rt -> right -> left = 0;
                   UST(rt -> right);
                   UST(rt);
                   add[++adds] = make_pair(group, die -> p.second);
             }
         }
         tree[root].clear();
         tree[root].push_back(group);
         for (i = 1; i <= adds; i++)
         {
             Insert(add[i]);
         }
         return;
     }
     Update(root << 1, nowleft, mid, askleft, askright);
     Update((root << 1) | 1, mid + 1, nowright, askleft, askright);

     return;
}

long long Solve(int total)
{
int  nh, nv, i, j, ts, temp, pointer, next, flag, l, r, a, b, p, q, ad, one, two, rank;
long long all;
map <pair <int, int>, bool>::iterator it;

     nh = nv = nnx = nny = all = result = 0;
     for (i = 1; i <= total; i++)
     {
         x[++nnx] = doing[i].fx;
         x[++nnx] = doing[i].tx;
         y[++nny] = doing[i].fy;
         y[++nny] = doing[i].ty;
         if  (doing[i].fx != doing[i].tx)
         {
             hh[++nh] = doing[i];
         }   else
         {
             vv[++nv] = doing[i];
         }
         all += doing[i].tx - doing[i].fx +
                doing[i].ty - doing[i].fy;
     }

     for (i = 1; i <= nh; i++)
     {
         up[i] = i;
         scale[i] = 1;
     }

     sort(x + 1, x + nnx + 1);

     for (i = j = 1; i < nnx; i++)
     if  (x[i + 1] != x[j])
     {
         x[++j] = x[i + 1];
     }
     nnx = j;

     sort(y + 1, y + nny + 1);

     for (i = j = 1; i < nny; i++)
     if  (y[i + 1] != y[j])
     {
         y[++j] = y[i + 1];
     }
     nny = j;

     memset(last, 0, 4 * nnx + 4);
     sf = 0;

     for (i = 1; i <= nh; i++)
     {
         Addedges(X(hh[i].fx), i, 0);
         Addedges(X(hh[i].tx), i, 2);
     }
     for (i = 1; i <= nv; i++)
     {
         Addedges(X(vv[i].fx), i, 1);
     }

     Clear(1, 1, nny);

     vs = 0;
     stree[++vs] = ST(0, 2, make_pair(-999999999, -999999999));
     rt = &stree[vs];
     stree[++vs] = ST(rt, 1, make_pair(999999999, 999999999));
     rt -> right = &stree[vs];

     for (i = 1; i <= nnx; i++)
     {
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 0)
             {
                 continue;
             }
             ad = Y(hh[next].fy);
             Force(1, 1, nny, ad, ad, next);
             Insert(make_pair(next, ad));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 1)
             {
                 continue;
             }
             firsttime = true;
             Update(1, 1, nny, Y(vv[next].fy), Y(vv[next].ty));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 2)
             {
                 continue;
             }
             rank = Findkth(make_pair(Up(next), Y(hh[next].fy)));
             Find(rank - 1, 0);
             Find(rank + 1, rt);
             rt -> right -> left = 0;
             UST(rt -> right);
             UST(rt);
         }
     }

     return all - result;
}

int main()
{
int nh, nv, n, i, j, fx, fy, tx, ty, total, pointer, next, flag, temp;
long long answer;

//    freopen("e.in", "r", stdin);
//    freopen("e.out", "w", stdout);

    srand((unsigned) time (0));

    nx = ny = nh = nv = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d%d%d", &fx, &fy, &tx, &ty);
        xx[++nx] = fx;
        xx[++nx] = tx;
        yy[++ny] = fy;
        yy[++ny] = ty;
        a[i] = Seg(fx, fy, tx, ty, i);
        if  (fx != tx)
        {
            h[++nh] = Seg(fx, fy, tx, ty, i);
        }   else
        {
            v[++nv] = Seg(fx, fy, tx, ty, i);
        }
    }

    sort(xx + 1, xx + nx + 1);
    for (i = j = 1; i < nx; i++)
    if  (xx[i + 1] != xx[j])
    {
        xx[++j] = xx[i + 1];
    }
    nx = j;

    sort(yy + 1, yy + ny + 1);
    for (i = j = 1; i < ny; i++)
    if  (yy[i + 1] != yy[j])
    {
        yy[++j] = yy[i + 1];
    }
    ny = j;

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= nh; i++)
    {
        Addedge(Halfx(h[i].fx), h[i].number, 0);
        Addedge(Halfx(h[i].tx), h[i].number, 2);
    }
    for (i = 1; i <= nv; i++)
    {
        Addedge(Halfx(v[i].fx), v[i].number, 1);
    }

    for (i = 1; i <= n; i++)
    {
        father[i] = i;
    }
    memset(tree1, 0, sizeof(tree1));
    for (i = 1; i <= nx; i++)
    {
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 0)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            Force1(1, 1, ny, temp, temp, next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 1)
            {
                continue;
            }
            Update1(1, 1, ny, Halfy(a[next].fy), Halfy(a[next].ty), next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 2)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            belong[next] = Ask1(1, 1, ny, temp, temp);
            Force1(1, 1, ny, temp, temp, 0);
        }
    }
    for (i = 1; i <= nv; i++)
    {
        belong[v[i].number] = Father(v[i].number);
    }
    for (i = 1; i <= n; i++)
    {
        belong[i] = Father(belong[i]);
    }

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= n; i++)
    {
        Addedge(belong[i], i, 0);
    }
    answer = 0;
    for (i = 1; i <= n; i++)
    {
        total = 0;
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            doing[++total] = a[next];
        }
        if  (total == 0)
        {
            continue;
        }
        answer = max(answer, Solve(total));
    }

    printf("%I64d\n", answer);

    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;

struct Seg
{
       int fx, fy, tx, ty, number;
       Seg () {}
       Seg (int _fx, int _fy, int _tx, int _ty, int _number) :
           fx(_fx), fy(_fy), tx(_tx), ty(_ty), number(_number) {}
}      a[200050], h[200050], v[200050], hh[200050], vv[200050], doing[200050];

struct Tedge
{
       int to, flag, next;
}      edge[1000050], mem[1000050];

struct Tree1
{
       int f, down;
}      tree1[10000050];

int now, sf, nx, ny, nnx, nny, group, first[1000050], last[1000050], up[1000050], scale[1000050];
int x[1000050], y[1000050], xx[1000050], yy[1000050], father[200050];
int belong[200050];
bool firsttime;
vector <pair <int, int> > tree[4000050];
long long result;
map <pair <int, int>, bool> f;

int Rand()
{
    return (rand() << 15) | rand();
}

void Addedge(int x, int y, int flag)
{
     edge[++now].to = y;
     edge[now].flag = flag;
     edge[now].next = first[x];
     first[x] = now;

     return;
}

void Addedges(int x, int y, int flag)
{
     mem[++sf].to = y;
     mem[sf].flag = flag;
     mem[sf].next = last[x];
     last[x] = sf;

     return;
}

int  Halfx(int ask)
{
int  low, mid, high;

     low = 0;
     high = nx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (xx[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Halfy(int ask)
{
int  low, mid, high;

     low = 0;
     high = ny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (yy[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Father(int current)
{
     if  (father[current] != current)
     {
         father[current] = Father(father[current]);
     }

     return father[current];
}

void Down1(int root)
{
     if  (tree1[root].down != 0)
     {
         if  (tree1[root].f == 0)
         {
             tree1[root].down = 0;
             return;
         }
         father[Father(tree1[root].f)] = Father(tree1[root].down);
         if  (tree1[root << 1].down != 0)
         {
             if  (tree1[root << 1].f != 0)
             {
                 father[Father(tree1[root << 1].down)] = Father(tree1[root].down);
             }
         }
         if  (tree1[(root << 1) | 1].down != 0)
         {
             if  (tree1[(root << 1) | 1].f != 0)
             {
                 father[Father(tree1[(root << 1) | 1].down)] = Father(tree1[root].down);
             }
         }
         tree1[root << 1].down = tree1[root].down;
         tree1[(root << 1) | 1].down = tree1[root].down;
         tree1[root].down = 0;
     }

     return;
}

void Force1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         tree1[root].f = news;
         return;
     }
     Force1(root << 1, nowleft, mid, askleft, askright, news);
     Force1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

void Update1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         if  (tree1[root].f != 0)
         {
             tree1[root].down = news;
             Down1(root);
         }
         return;
     }
     Update1(root << 1, nowleft, mid, askleft, askright, news);
     Update1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

int  Ask1(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return 0;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return Father(tree1[root].f);
     }

     return max(Ask1(root << 1, nowleft, mid, askleft, askright),
                Ask1((root << 1) | 1, mid + 1, nowright, askleft, askright));
}

int  X(int ask)
{
int  low, mid, high;

     low = 0;
     high = nnx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (x[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Y(int ask)
{
int  low, mid, high;

     low = 0;
     high = nny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (y[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Up(int current)
{
     if  (up[current] != current)
     {
         up[current] = Up(up[current]);
     }

     return up[current];
}

void Clear(int root, int nowleft, int nowright)
{
int  mid = (nowleft + nowright) >> 1;

     tree[root].clear();
     if  (nowleft == nowright)
     {
         return;
     }
     Clear(root << 1, nowleft, mid);
     Clear((root << 1) | 1, mid + 1, nowright);

     return;
}

void Force(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     tree[root].push_back(make_pair(news, 1));
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Force(root << 1, nowleft, mid, askleft, askright, news);
     Force((root << 1) | 1, mid + 1, nowright, askleft, askright, news);

     return;
}

void Update(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1, sizes, next, temp, i;
map <pair <int, int>, bool>::iterator it;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         temp = tree[root].size();
         if  (temp == 0)
         {
             return;
         }
         sizes = 0;
         for (i = 0; i < temp; i++)
         {
             next = Up(tree[root][i].first);
             sizes += tree[root][i].second;
             result += tree[root][i].second;
             if  (firsttime)
             {
                 result--;
                 group = next;
                 firsttime = false;
                 continue;
             }
             if  (group == next)
             {
                 continue;
             }
             result--;
             if  (scale[group] < scale[next])
             {
                 swap(group, next);
             }
             scale[group] += scale[next];
             up[next] = group;
             while (true)
             {
                   it = f.lower_bound(make_pair(next, -999999999));
                   if  (it -> first.first != next)
                   {
                       break;
                   }
                   f.insert(make_pair(make_pair(group, it -> first.second), true));
                   f.erase(it);
             }
         }
         tree[root].clear();
         tree[root].push_back(make_pair(group, sizes));
         return;
     }
     Update(root << 1, nowleft, mid, askleft, askright);
     Update((root << 1) | 1, mid + 1, nowright, askleft, askright);

     return;
}

void Erase(int root, int nowleft, int nowright, int askleft, int askright, int ask)
{
int  mid = (nowleft + nowright) >> 1, temp, i;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     temp = tree[root].size();
     for (i = 0; i < temp; i++)
     if  (Up(tree[root][i].first) == Up(ask))
     {
         tree[root][i].second--;
         if  (tree[root][i].second == 0)
         {
             tree[root].erase(tree[root].begin() + i);
         }
         break;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Erase(root << 1, nowleft, mid, askleft, askright, ask);
     Erase((root << 1) | 1, mid + 1, nowright, askleft, askright, ask);

     return;
}

long long Solve(int total)
{
int  nh, nv, i, j, ts, temp, pointer, next, flag, l, r, a, b, p, q, ad, one, two;
long long all;
map <pair <int, int>, bool>::iterator it;

     nh = nv = nnx = nny = all = result = 0;
     for (i = 1; i <= total; i++)
     {
         x[++nnx] = doing[i].fx;
         x[++nnx] = doing[i].tx;
         y[++nny] = doing[i].fy;
         y[++nny] = doing[i].ty;
         if  (doing[i].fx != doing[i].tx)
         {
             hh[++nh] = doing[i];
         }   else
         {
             vv[++nv] = doing[i];
         }
         all += doing[i].tx - doing[i].fx +
                doing[i].ty - doing[i].fy;
     }

     for (i = 1; i <= nh; i++)
     {
         up[i] = i;
         scale[i] = 1;
     }

     sort(x + 1, x + nnx + 1);

     for (i = j = 1; i < nnx; i++)
     if  (x[i + 1] != x[j])
     {
         x[++j] = x[i + 1];
     }
     nnx = j;

     sort(y + 1, y + nny + 1);

     for (i = j = 1; i < nny; i++)
     if  (y[i + 1] != y[j])
     {
         y[++j] = y[i + 1];
     }
     nny = j;

     memset(last, 0, 4 * nnx + 4);
     sf = 0;

     for (i = 1; i <= nh; i++)
     {
         Addedges(X(hh[i].fx), i, 0);
         Addedges(X(hh[i].tx), i, 2);
     }
     for (i = 1; i <= nv; i++)
     {
         Addedges(X(vv[i].fx), i, 1);
     }

     Clear(1, 1, nny);
     f.clear();
     f.insert(make_pair(make_pair(-999999999, -999999999), true));
     f.insert(make_pair(make_pair(999999999, 999999999), true));
     for (i = 1; i <= nnx; i++)
     {
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 0)
             {
                 continue;
             }
             ad = Y(hh[next].fy);
             Force(1, 1, nny, ad, ad, next);
             f.insert(make_pair(make_pair(next, ad), true));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 1)
             {
                 continue;
             }
             firsttime = true;
             Update(1, 1, nny, Y(vv[next].fy), Y(vv[next].ty));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 2)
             {
                 continue;
             }
             one = two = 999999999;
             ad = Y(hh[next].fy);
             temp = Up(next);
             it = f.find(make_pair(temp, ad));
             it--;
             if  (it -> first.first == temp)
             {
                 one = it -> first.second;
             }
             it++;
             it++;
             if  (it -> first.first == temp)
             {
                 two = it -> first.second;
             }
             it--;
             f.erase(it);
             Erase(1, 1, nny, ad, ad, next);
         }
     }

     return all - result;
}

int main()
{
int nh, nv, n, i, j, fx, fy, tx, ty, total, pointer, next, flag, temp;
long long answer;

//    freopen("e.in", "r", stdin);
//    freopen("e.out", "w", stdout);

    srand((unsigned) time (0));

    nx = ny = nh = nv = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d%d%d", &fx, &fy, &tx, &ty);
        xx[++nx] = fx;
        xx[++nx] = tx;
        yy[++ny] = fy;
        yy[++ny] = ty;
        a[i] = Seg(fx, fy, tx, ty, i);
        if  (fx != tx)
        {
            h[++nh] = Seg(fx, fy, tx, ty, i);
        }   else
        {
            v[++nv] = Seg(fx, fy, tx, ty, i);
        }
    }

    sort(xx + 1, xx + nx + 1);
    for (i = j = 1; i < nx; i++)
    if  (xx[i + 1] != xx[j])
    {
        xx[++j] = xx[i + 1];
    }
    nx = j;

    sort(yy + 1, yy + ny + 1);
    for (i = j = 1; i < ny; i++)
    if  (yy[i + 1] != yy[j])
    {
        yy[++j] = yy[i + 1];
    }
    ny = j;

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= nh; i++)
    {
        Addedge(Halfx(h[i].fx), h[i].number, 0);
        Addedge(Halfx(h[i].tx), h[i].number, 2);
    }
    for (i = 1; i <= nv; i++)
    {
        Addedge(Halfx(v[i].fx), v[i].number, 1);
    }

    for (i = 1; i <= n; i++)
    {
        father[i] = i;
    }
    memset(tree1, 0, sizeof(tree1));
    for (i = 1; i <= nx; i++)
    {
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 0)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            Force1(1, 1, ny, temp, temp, next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 1)
            {
                continue;
            }
            Update1(1, 1, ny, Halfy(a[next].fy), Halfy(a[next].ty), next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 2)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            belong[next] = Ask1(1, 1, ny, temp, temp);
            Force1(1, 1, ny, temp, temp, 0);
        }
    }
    for (i = 1; i <= nv; i++)
    {
        belong[v[i].number] = Father(v[i].number);
    }
    for (i = 1; i <= n; i++)
    {
        belong[i] = Father(belong[i]);
    }

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= n; i++)
    {
        Addedge(belong[i], i, 0);
    }
    answer = 0;
    for (i = 1; i <= n; i++)
    {
        total = 0;
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            doing[++total] = a[next];
        }
        if  (total == 0)
        {
            continue;
        }
        answer = max(answer, Solve(total));
    }

    printf("%I64d\n", answer);

    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define left son[0]
#define right son[1]

struct Seg
{
       int fx, fy, tx, ty, number;
       Seg () {}
       Seg (int _fx, int _fy, int _tx, int _ty, int _number) :
           fx(_fx), fy(_fy), tx(_tx), ty(_ty), number(_number) {}
}      a[200050], h[200050], v[200050], hh[200050], vv[200050], doing[200050];

struct ST
{
       int size;
       pair <int, int> p;
       ST *father, *son[2];
       ST () {}
       ST (ST *F, int S, pair <int, int> P)
       {
          father = F;
          size = S;
          p = P;
          left = right = 0;
          return;
       }
}      *rt, stree[10000050];

struct Tedge
{
       int to, flag, next;
}      edge[1000050], mem[1000050];

struct Tree1
{
       int f, down;
}      tree1[10000050];

int now, sf, nx, ny, nnx, nny, group, vs, ss, first[1000050], last[1000050], up[1000050], scale[1000050];
int x[1000050], y[1000050], xx[1000050], yy[1000050], father[200050];
int belong[200050], need[1000050];
bool firsttime, vis[1000050];
vector <int> tree[4000050];
long long result;
pair <int, int> add[1000050];

int Rand()
{
    return (rand() << 15) | rand();
}

void Addedge(int x, int y, int flag)
{
     edge[++now].to = y;
     edge[now].flag = flag;
     edge[now].next = first[x];
     first[x] = now;

     return;
}

void Addedges(int x, int y, int flag)
{
     mem[++sf].to = y;
     mem[sf].flag = flag;
     mem[sf].next = last[x];
     last[x] = sf;

     return;
}

int  Halfx(int ask)
{
int  low, mid, high;

     low = 0;
     high = nx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (xx[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Halfy(int ask)
{
int  low, mid, high;

     low = 0;
     high = ny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (yy[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Father(int current)
{
     if  (father[current] != current)
     {
         father[current] = Father(father[current]);
     }

     return father[current];
}

void Down1(int root)
{
     if  (tree1[root].down != 0)
     {
         if  (tree1[root].f == 0)
         {
             tree1[root].down = 0;
             return;
         }
         father[Father(tree1[root].f)] = Father(tree1[root].down);
         if  (tree1[root << 1].down != 0)
         {
             if  (tree1[root << 1].f != 0)
             {
                 father[Father(tree1[root << 1].down)] = Father(tree1[root].down);
             }
         }
         if  (tree1[(root << 1) | 1].down != 0)
         {
             if  (tree1[(root << 1) | 1].f != 0)
             {
                 father[Father(tree1[(root << 1) | 1].down)] = Father(tree1[root].down);
             }
         }
         tree1[root << 1].down = tree1[root].down;
         tree1[(root << 1) | 1].down = tree1[root].down;
         tree1[root].down = 0;
     }

     return;
}

void Force1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         tree1[root].f = news;
         return;
     }
     Force1(root << 1, nowleft, mid, askleft, askright, news);
     Force1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

void Update1(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         if  (tree1[root].f != 0)
         {
             tree1[root].down = news;
             Down1(root);
         }
         return;
     }
     Update1(root << 1, nowleft, mid, askleft, askright, news);
     Update1((root << 1) | 1, mid + 1, nowright, askleft, askright, news);
     tree1[root].f = max(tree1[root << 1].f, tree1[(root << 1) | 1].f);

     return;
}

int  Ask1(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1;

     Down1(root);
     if  (nowright < askleft || askright < nowleft)
     {
         return 0;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         return Father(tree1[root].f);
     }

     return max(Ask1(root << 1, nowleft, mid, askleft, askright),
                Ask1((root << 1) | 1, mid + 1, nowright, askleft, askright));
}

int  X(int ask)
{
int  low, mid, high;

     low = 0;
     high = nnx + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (x[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

int  Y(int ask)
{
int  low, mid, high;

     low = 0;
     high = nny + 1;
     while (low + 1 < high)
     {
           mid = (low + high) >> 1;
           if  (y[mid] <= ask)
           {
               low = mid;
           }   else
           {
               high = mid;
           }
     }

     return low;
}

// stree

void UST(ST *current)
{
     current -> size = 1;
     if  (current -> left)
     {
         current -> size += current -> left -> size;
     }
     if  (current -> right)
     {
         current -> size += current -> right -> size;
     }

     return;
}

void Rotate(ST *current, int flag)
{
     current -> father -> son[flag ^ 1] = current -> son[flag];
     if  (current -> son[flag])
     {
         current -> son[flag] -> father = current -> father;
     }
     current -> son[flag] = current -> father;
     if  (current -> father -> father)
     {
         current -> father -> father ->
         son[current -> father -> father -> left != current -> father] = current;
     }
     current -> father = current -> father -> father;
     current -> son[flag] -> father = current;
     UST(current -> son[flag]);

     return;
}

void Splay(ST *current, ST *target)
{
     while (current -> father != target)
     {
           if  (current -> father -> father == target)
           {
               Rotate(current, current -> father -> right != current);
           }   else
           if  (current -> father -> father -> left == current -> father &&
               current -> father -> left == current)
           {
               Rotate(current -> father, 1);
               Rotate(current, 1);
           }   else
           if  (current -> father -> father -> right == current -> father &&
               current -> father -> right == current)
           {
               Rotate(current -> father, 0);
               Rotate(current, 0);
           }   else
           {
               Rotate(current, current -> father -> right != current);
               Rotate(current, current -> father -> right != current);
           }
     }
     UST(current);
     if  (!target)
     {
         rt = current;
     }

     return;
}

void Find(int ask, ST *target)
{
ST   *current = rt;

     while (current)
     {
           if  (current -> left)
           {
               if  (ask == current -> left -> size + 1)
               {
                   break;
               }
           }   else
           if  (ask == 1)
           {
               break;
           }
           if  (current -> left && ask < current -> left -> size + 1)
           {
               current = current -> left;
           }   else
           {
               ask--;
               if  (current -> left)
               {
                   ask -= current -> left -> size;
               }
               current = current -> right;
           }
     }
     Splay(current, target);

     return;

     return;
}

void Insert(pair <int, int> ask)
{
ST   *current = rt;

     while (current)
     {
           if  (ask < current -> p)
           {
               if  (current -> left)
               {
                   current = current -> left;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> left = &stree[vs];
                   Splay(current -> left, 0);
                   return;
               }
           }   else
           {
               if  (current -> right)
               {
                   current = current -> right;
               }   else
               {
                   stree[++vs] = ST(current, 1, ask);
                   current -> right = &stree[vs];
                   Splay(current -> right, 0);
                   return;
               }
           }
     }

     return;
}

int  Findkth(pair <int, int> ask)
{
ST   *current = rt, *best = rt;

     while (current)
     {
           if  (ask <= current -> p)
           {
               best = current;
               current = current -> left;
           }   else
           {
               current = current -> right;
           }
     }
     Splay(best, 0);
     if  (rt -> left)
     {
         return rt -> left -> size + 1;
     }
     return 1;
}

// stree

int  Up(int current)
{
     if  (up[current] != current)
     {
         up[current] = Up(up[current]);
     }

     return up[current];
}

void Clear(int root, int nowleft, int nowright)
{
int  mid = (nowleft + nowright) >> 1;

     tree[root].clear();
     if  (nowleft == nowright)
     {
         return;
     }
     Clear(root << 1, nowleft, mid);
     Clear((root << 1) | 1, mid + 1, nowright);

     return;
}

void Force(int root, int nowleft, int nowright, int askleft, int askright, int news)
{
int  mid = (nowleft + nowright) >> 1;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     tree[root].push_back(news);
     if  (askleft <= nowleft && nowright <= askright)
     {
         return;
     }
     Force(root << 1, nowleft, mid, askleft, askright, news);
     Force((root << 1) | 1, mid + 1, nowright, askleft, askright, news);

     return;
}

void Update(int root, int nowleft, int nowright, int askleft, int askright)
{
int  mid = (nowleft + nowright) >> 1, one, two, next, temp, i, rank, ss, adds;
ST  *die;

     if  (nowright < askleft || askright < nowleft)
     {
         return;
     }
     if  (askleft <= nowleft && nowright <= askright)
     {
         temp = tree[root].size();
         if  (temp == 0)
         {
             return;
         }

         for (adds = ss = i = 0; i < temp; i++)
         {
             next = Up(tree[root][i]);
             if  (!vis[next])
             {
                 vis[next] = true;
                 need[++ss] = next;
             }
         }

         for (i = 1; i <= ss; i++)
         {
             vis[need[i]] = false;
             next = Up(need[i]);
             one = Findkth(make_pair(next, nowleft));
             two = Findkth(make_pair(next, nowright + 1));
             if  (one >= two)
             {
                 continue;
             }
             result += two - one;
             if  (firsttime)
             {
                 result--;
                 group = next;
                 firsttime = false;
                 continue;
             }
             if  (group == next)
             {
                 continue;
             }
             result--;
             if  (scale[group] < scale[next])
             {
                 swap(group, next);
             }
             scale[group] += scale[next];
             up[next] = group;
             while (true)
             {
                   rank = Findkth(make_pair(next, -999999999));
                   die = rt;
                   if  (die -> p.first != next)
                   {
                       break;
                   }
                   Find(rank - 1, 0);
                   Find(rank + 1, rt);
                   rt -> right -> left = 0;
                   UST(rt -> right);
                   UST(rt);
                   add[++adds] = make_pair(group, die -> p.second);
             }
         }
         tree[root].clear();
         tree[root].push_back(group);
         for (i = 1; i <= adds; i++)
         {
             Insert(make_pair(Up(add[i].first), add[i].second));
         }
         return;
     }
     Update(root << 1, nowleft, mid, askleft, askright);
     Update((root << 1) | 1, mid + 1, nowright, askleft, askright);

     return;
}

long long Solve(int total)
{
int  nh, nv, i, j, ts, temp, pointer, next, flag, l, r, a, b, p, q, ad, one, two, rank;
long long all;
map <pair <int, int>, bool>::iterator it;

     nh = nv = nnx = nny = all = result = 0;
     for (i = 1; i <= total; i++)
     {
         x[++nnx] = doing[i].fx;
         x[++nnx] = doing[i].tx;
         y[++nny] = doing[i].fy;
         y[++nny] = doing[i].ty;
         if  (doing[i].fx != doing[i].tx)
         {
             hh[++nh] = doing[i];
         }   else
         {
             vv[++nv] = doing[i];
         }
         all += doing[i].tx - doing[i].fx +
                doing[i].ty - doing[i].fy;
     }

     for (i = 1; i <= nh; i++)
     {
         up[i] = i;
         scale[i] = 1;
     }

     sort(x + 1, x + nnx + 1);

     for (i = j = 1; i < nnx; i++)
     if  (x[i + 1] != x[j])
     {
         x[++j] = x[i + 1];
     }
     nnx = j;

     sort(y + 1, y + nny + 1);

     for (i = j = 1; i < nny; i++)
     if  (y[i + 1] != y[j])
     {
         y[++j] = y[i + 1];
     }
     nny = j;

     memset(last, 0, 4 * nnx + 4);
     sf = 0;

     for (i = 1; i <= nh; i++)
     {
         Addedges(X(hh[i].fx), i, 0);
         Addedges(X(hh[i].tx), i, 2);
     }
     for (i = 1; i <= nv; i++)
     {
         Addedges(X(vv[i].fx), i, 1);
     }

     Clear(1, 1, nny);

     vs = 0;
     stree[++vs] = ST(0, 2, make_pair(-999999999, -999999999));
     rt = &stree[vs];
     stree[++vs] = ST(rt, 1, make_pair(999999999, 999999999));
     rt -> right = &stree[vs];

     for (i = 1; i <= nnx; i++)
     {
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 0)
             {
                 continue;
             }
             ad = Y(hh[next].fy);
             Force(1, 1, nny, ad, ad, next);
             Insert(make_pair(next, ad));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 1)
             {
                 continue;
             }
             firsttime = true;
             Update(1, 1, nny, Y(vv[next].fy), Y(vv[next].ty));
         }
         for (pointer = last[i]; pointer; pointer = mem[pointer].next)
         {
             next = mem[pointer].to;
             flag = mem[pointer].flag;
             if  (flag != 2)
             {
                 continue;
             }
             rank = Findkth(make_pair(Up(next), Y(hh[next].fy)));
             Find(rank - 1, 0);
             Find(rank + 1, rt);
             rt -> right -> left = 0;
             UST(rt -> right);
             UST(rt);
         }
     }

     return all - result;
}

int main()
{
int nh, nv, n, i, j, fx, fy, tx, ty, total, pointer, next, flag, temp;
long long answer;

//    freopen("e.in", "r", stdin);
//    freopen("e.out", "w", stdout);

    srand((unsigned) time (0));

    nx = ny = nh = nv = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d%d%d", &fx, &fy, &tx, &ty);
        xx[++nx] = fx;
        xx[++nx] = tx;
        yy[++ny] = fy;
        yy[++ny] = ty;
        a[i] = Seg(fx, fy, tx, ty, i);
        if  (fx != tx)
        {
            h[++nh] = Seg(fx, fy, tx, ty, i);
        }   else
        {
            v[++nv] = Seg(fx, fy, tx, ty, i);
        }
    }

    sort(xx + 1, xx + nx + 1);
    for (i = j = 1; i < nx; i++)
    if  (xx[i + 1] != xx[j])
    {
        xx[++j] = xx[i + 1];
    }
    nx = j;

    sort(yy + 1, yy + ny + 1);
    for (i = j = 1; i < ny; i++)
    if  (yy[i + 1] != yy[j])
    {
        yy[++j] = yy[i + 1];
    }
    ny = j;

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= nh; i++)
    {
        Addedge(Halfx(h[i].fx), h[i].number, 0);
        Addedge(Halfx(h[i].tx), h[i].number, 2);
    }
    for (i = 1; i <= nv; i++)
    {
        Addedge(Halfx(v[i].fx), v[i].number, 1);
    }

    for (i = 1; i <= n; i++)
    {
        father[i] = i;
    }
    memset(tree1, 0, sizeof(tree1));
    for (i = 1; i <= nx; i++)
    {
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 0)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            Force1(1, 1, ny, temp, temp, next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 1)
            {
                continue;
            }
            Update1(1, 1, ny, Halfy(a[next].fy), Halfy(a[next].ty), next);
        }

        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            flag = edge[pointer].flag;
            if  (flag != 2)
            {
                continue;
            }
            temp = Halfy(a[next].fy);
            belong[next] = Ask1(1, 1, ny, temp, temp);
            Force1(1, 1, ny, temp, temp, 0);
        }
    }
    for (i = 1; i <= nv; i++)
    {
        belong[v[i].number] = Father(v[i].number);
    }
    for (i = 1; i <= n; i++)
    {
        belong[i] = Father(belong[i]);
    }

    memset(first, 0, sizeof(first));
    now = 0;
    for (i = 1; i <= n; i++)
    {
        Addedge(belong[i], i, 0);
    }
    answer = 0;
    for (i = 1; i <= n; i++)
    {
        total = 0;
        for (pointer = first[i]; pointer; pointer = edge[pointer].next)
        {
            next = edge[pointer].to;
            doing[++total] = a[next];
        }
        if  (total == 0)
        {
            continue;
        }
        answer = max(answer, Solve(total));
    }

    printf("%I64d\n", answer);

    return 0;
}