#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=0;
    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=0;
    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() {
    //freopen("input.txt","r",stdin);
    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=left[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];
            int nDSU=0;
            int nl=0;
            int nr=0;
            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);
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]-=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=cnt.number-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=findsum(yr)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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,best,fen[1000000],xend[1000000],ybegin[1000000],yend[1000000],realx[1000000],realy[1000000],ans[1000000],parent[1000000];
event events[1000000];
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=0;
    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=0;
    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) {
    int s=0;
    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) {
    if (*s.begin()>y) return;
    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;
    }
    if (y<cnt.right) {
        it2++;
        int nl=*it2;
        int nsize=findsum(cnt.right)-findsum(nl-1);
        lefts[nl].right=cnt.right;
        lefts[nl].dsu=lefts[l].dsu;
        lefts[nl].number=nsize;
    }
}
int main() {
    ios_base::sync_with_stdio(0);
    init();
    make_events();
    compcount=0;
    best=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 it=lefts.begin();
            int l1=it->first;
            if (l1<=y) {
                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 divide(y,l);
        }
        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];
            int nDSU=0;
            int nl=0;
            int nr=0;
            map<int, P>::iterator it=lefts.lower_bound(yl);
            it--;
            int l=it->first;
            P cnt=lefts[l];
            if (cnt.right>=yl) {
                nl=l;
                nr=cnt.right;
                nDSU=cnt.dsu;
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]+=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                lefts.erase(l);
            }
            while (lefts.end()!=lefts.begin()) {
                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=cnt.dsu;
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    ans[nDSU]+=ans[findset(cnt.dsu)];
                    parent[findset(cnt.dsu)]=nDSU;

                }
                if (yr>=cnt.right) ans[nDSU]-=cnt.number-1;
                lefts.erase(l);
            }
            it=lefts.upper_bound(yr);
            it--;
            l=it->first;
            cnt=lefts[l];
            if (cnt.right>=yr) {
                nr=cnt.right;
                if (nDSU==0) {
                    nDSU=cnt.dsu;
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    ans[nDSU]+=ans[findset(cnt.dsu)];
                    parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]+=findsum(yr)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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() {
    freopen("input.txt","r",stdin);
    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];
            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 <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=0;
    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=0;
    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) {
    int s=0;
    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;
    }
    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() {
  //  freopen("input.txt","r",stdin);
    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 divide(y,l);
        }
        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];
            int nDSU=0;
            int nl=0;
            int nr=0;
            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);
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]-=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=cnt.number-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=findsum(cnt.right)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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=0;
    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=0;
    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) {
    int s=0;
    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) {
    if (*s.begin()>y) return;
    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;
    }
    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() {
    //freopen("input.txt","r",stdin);
    ios_base::sync_with_stdio(0);
    init();
    make_events();
    compcount=0;
    best=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 it=lefts.begin();
            int l1=it->first;
            if (l1<=y) {
                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 divide(y,l);
        }
        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];
            int nDSU=0;
            int nl=0;
            int nr=0;
            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);
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]+=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                lefts.erase(l);
            }
            while (lefts.end()!=lefts.begin()) {
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                if (yr>=cnt.right) ans[nDSU]-=cnt.number-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]+=findsum(yr)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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=0;
    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=0;
    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) {
    int s=0;
    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;
    }
    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() {
  //  freopen("input.txt","r",stdin);
    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 divide(y,l);
        }
        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];
            int nDSU=0;
            int nl=0;
            int nr=0;
            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);
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]-=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=cnt.number-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=findsum(yr)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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[1001000],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=0;
    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 tt=0;
    for (int i=1;i<=v-1;i++)
        if (events[i].x<events[i+1].x || (events[i].x==events[i] && events[i].type<=events[i+1].type)) tt++;
    if (tt!=v-1)*/
}
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<=1000000) {
        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() {
   // freopen("input.txt","r",stdin);
    ios_base::sync_with_stdio(0);
    init();
    make_events();
    compcount=0;
    best=0;
    s.insert(0);
    s.insert(2000000);
    lefts[2000000].right=2000000;
    lefts[0].right=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];
            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)+dif;
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#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=0;
    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=0;
    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() {
    freopen("input.txt","r",stdin);
    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;
            if (y==0) return;
            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;
            if (y==0) return;
            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 divide(y,l);
        }
        if (events[i].type==2) {
            int yl=events[i].y;
            int yr=events[i].righty;
            if (yl==0) return;
            if (realy[yr]-realy[yl]>best) best=realy[yr]-realy[yl];
            int nDSU=0;
            int nl=0;
            int nr=0;
            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);
                ans[nDSU]+=realy[yr]-realy[yl];
                ans[nDSU]-=findsum(min(cnt.right,yr))-findsum(yl-1)-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=cnt.number-1;
                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);
                    ans[nDSU]+=realy[yr]-realy[yl];
                } else {
                    if (nDSU==findset(cnt.dsu)) ans[nDSU]--;
                    if (nDSU!=findset(cnt.dsu)) ans[nDSU]+=ans[findset(cnt.dsu)];
                    if (nDSU!=findset(cnt.dsu)) parent[findset(cnt.dsu)]=nDSU;
                }
                ans[nDSU]-=findsum(yr)-findsum(l-1)-1;
                lefts.erase(l);
            }
            if (nDSU!=0) {
                lefts[nl].right=nr;
                lefts[nl].dsu=nDSU;
                lefts[nl].number=findsum(nr)-findsum(nl-1);
            }
        }
    }
    for (int i=1;i<=compcount;i++)
        if (ans[i]>best) best=ans[i];
    cout << best << endl;
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];

set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}

int getkth(int k, int nl, int nr, int v){
	if (nl == nr) {
		assert(v == 1 &&val[k]==1);
		return nl;
	}
	int nm = (nl + nr) >> 1;
	if (v <= val[2 * k + 1]) return getkth(2 * k + 1, nl, nm, v);
	else return getkth(2 * k + 2, nm + 1, nr, v - val[2 * k + 1]);
}
int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

map<PII, int> gs;
int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	map<PII, int>::iterator gr;
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			if (!gs.empty()){
				gr = gs.upper_bound(PII(x[id][0], INF));
				if (gr != gs.begin()) {
					gr--;
					int l = gr->first.first, r = gr->first.second, g = gr->second;
					if (l <= x[id][0] && x[id][0] <= r) {
						assert(x[id][0] - 1 >= l && x[id][0] + 1 <= r);
						assert(g != id);
						gs.erase(gr);
						int k, e;
						k = get(0, 0, X - 1, 0, x[id][0]);
						e = getkth(0, 0, X - 1, k);
						gs[PII(l, e)] = g;
						k = get(0, 0, X - 1, 0, x[id][0]);
						e = getkth(0, 0, X - 1, k + 1);
						gs[PII(e, r)] = g;
					}
				}
			}
			add(0, 0, X - 1, x[id][0], 1);
			gs[PII(x[id][0], x[id][0])] = id;
		}
		else if (e.tp == 2){
			gr = --gs.upper_bound(PII(x[id][0], INF));
			int l = gr->first.first, r = gr->first.second, g = gr->second;
			assert(l <= x[id][0] && x[id][0] <= r);
			if (l == r) {
				gs.erase(gr);
			} else if (l == x[id][0] || r == x[id][0]) {
				int eles = get(0, 0, X - 1, l, r);
				assert(eles > 1);
				gs.erase(gr);
				if (l == x[id][0]) {
					int k = get(0, 0, X - 1, 0, l);
					int e = getkth(0, 0, X - 1, k + 1);
					gs[PII(e, r)] = g;
				} else if (r == x[id][0]){
					int k = get(0, 0, X - 1, 0, r);
					int e = getkth(0, 0, X - 1, k - 1);
					gs[PII(l, e)] = g;
				}
			}
			add(0, 0, X - 1, x[id][0], -1);
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			emn[id] += n;
			if (!gs.empty()) {
				gr = gs.upper_bound(PII(x[id][1], INF));
				if (gr != gs.begin()) {
					gr--;
					int sl = INF, sr = -INF;
					while (1){
						bool b = 0;
						int l = gr->first.first, r = gr->first.second, g = gr->second;
						if (l <= x[id][1] && r >= x[id][0] && get(0, 0, X - 1, x[id][0], x[id][1]) > 0){
							unionset(g, id);
							sl = min(l, sl);
							sr = max(r, sr);
							if (gr == gs.begin()) b = 1;
							gs.erase(gr--);
							if (b) break;
						}
						else break;
					}
					if (sl != INF) gs[PII(sl, sr)] = find(id);
				}

			}
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];

set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k].insert(v);
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].erase(v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) remcomp(2 * k + 1, nl, nm, x, v);
	else remcomp(2 * k + 2, nm + 1, nr, x, v);
	if (comp[2 * k + 1].find(v) == comp[2 * k + 1].end()
		&& comp[2 * k + 2].find(v) == comp[2 * k + 2].end()){
		comp[k].erase(v);
	}
}
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		if (!comp[k].empty()){
			set<int>::iterator r;
			for (r = comp[k].begin(); r != comp[k].end(); r++)  {
				unionset(*r, v);
			}
			comp[k].clear();
			comp[k].insert(find(v));
		}
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) unicomp(2 * k + 1, nl, nm, l, r, v);
	if (r >= nm + 1) unicomp(2 * k + 2, nm + 1, nr, l, r, v);
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], find(id));
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			emn[id] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], id);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];
int P, pnxt[MAXP], pid[MAXP], ptl[MAXV], phd[MAXV], psd[MAXV];
int Q, markql[MAXN], markqr[MAXN];
void ip(int a, int b, int sd){
	pid[P] = b;
	psd[P] = sd;
	pnxt[P] = -1;
	if (phd[a] == -1) ptl[a] = phd[a] = P;
	else {
		pnxt[ptl[a]] = P;
		ptl[a] = P;
	}
	P++;
}
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
bool ucomp(int k, int v){
	int p = phd[k];
	while (p != -1){
		int id = pid[p];
		int rid = id > 0 ? find(id) : find(-id);
		int sd = psd[p];
		//cerr << id << " " << sd << endl;

		if (id < 0){	// remove
			if (sd == 0){
				markql[rid] = markqr[rid] = 0;
			} else if (sd == -1){
				markql[rid] = 0;
			} else if (sd == 1){
				markqr[rid] = 0;
			}
		}
		else {
			if (sd == 0){
				markql[rid] = markqr[rid] = Q;
			} else if (sd == -1){
				markql[rid] = Q;
			} else if (sd == 1){
				markqr[rid] = Q;
			}
		}
		p = pnxt[p];
	}
	p = phd[k];
	bool hit = 0;
	while (p != -1){
		int id = pid[p];
		if (id < 0) id = -id;
		int rid = find(id);
		if (markql[rid] == Q || markqr[rid] == Q){
			//cerr << "u " << rid << " " << v << endl;
 			unionset(rid, v);
		}
		p = pnxt[p];
	}
	if (hit){
		ptl[k] = phd[k] = -1;
		int vid = find(v);
		ip(k, vid, 0);
	}
	return hit;
}
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		ip(k, v, 0);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) {
		addcomp(2 * k + 1, nl, nm, x, v);
		ip(k, v, -1);
	} else {
		addcomp(2 * k + 2, nm + 1, nr, x, v);
		ip(k, v, 1);
	}
}
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		ucomp(k, v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) {
		unicomp(2 * k + 1, nl, nm, l, r, v);
	}
	if (r >= nm + 1){
		unicomp(2 * k + 2, nm + 1, nr, l, r, v);
	}
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	FILL(ptl, -1);
	FILL(phd, -1);
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
		if (x[i][0] > x[i][1]) swap(x[i][0], x[i][1]);
		if (y[i][0] > y[i][1]) swap(y[i][0], y[i][1]);
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << endl;
		Q = i + 1;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			addcomp(0, 0, X - 1, x[id][0], -id);
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			int rid = find(id);
			emn[rid] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], rid);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];

set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
int TOT;
set<int> at[MAXN];
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		at[v].insert(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k].insert(v);
	at[v].insert(k);
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].erase(v);
		at[v].erase(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) remcomp(2 * k + 1, nl, nm, x, v);
	else remcomp(2 * k + 2, nm + 1, nr, x, v);
	if (comp[2 * k + 1].find(v) == comp[2 * k + 1].end() && comp[2 * k + 2].find(v) == comp[2 * k + 2].end()){
		comp[k].erase(v);
		at[v].erase(k);
	}
}
int D, dod[MAXN*50];
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		set<int>::iterator r;
		D = 0;
		for (r = comp[k].begin(); r != comp[k].end(); r++) {
			unionset(*r, v);
			dod[D++] = *r;
		}
		int re = find(v);
		REP(i, 0, D){
			int x = dod[i];
			if (x == re) continue;
			for (r = at[x].begin(); r != at[x].end(); r++){
				comp[*r].erase(x);
				comp[*r].insert(re);
				at[re].insert(*r);
			}
			at[x].clear();
		}
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) unicomp(2 * k + 1, nl, nm, l, r, v);
	if (r >= nm + 1) unicomp(2 * k + 2, nm + 1, nr, l, r, v);
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], find(id));
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			emn[id] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], id);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];
int P, pnxt[MAXP], pid[MAXP], ptl[MAXV], phd[MAXV];
set<int> comp[MAXV];
void ip(int a, int b){
	pid[P] = b;
	pnxt[P] = -1;
	if (phd[a] == -1) ptl[a] = phd[a] = P;
	else {
		pnxt[ptl[a]] = P;
		ptl[a] = P;
	}
	P++;
}
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
int TOT;
set<int> at[MAXN];
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		at[v].insert(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k].insert(v);
	at[v].insert(k);
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].erase(v);
		at[v].erase(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) remcomp(2 * k + 1, nl, nm, x, v);
	else remcomp(2 * k + 2, nm + 1, nr, x, v);
	if (comp[2 * k + 1].find(v) == comp[2 * k + 1].end() && comp[2 * k + 2].find(v) == comp[2 * k + 2].end()){
		comp[k].erase(v);
		at[v].erase(k);
	}
}
int D, dod[MAXN];
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		set<int>::iterator r;
		D = 0;
		for (r = comp[k].begin(); r != comp[k].end(); r++) dod[D++] = *r;
		REP(i, 0, D) unionset(dod[i], v);
		int re = find(v);
		set<int> pos;
		REP(i, 0, D){
			int x = dod[i];
			if (x == re) continue;
			for (r = at[x].begin(); r != at[x].end(); r++){
				comp[*r].erase(x);
				pos.insert(*r);
			}
			at[x].clear();
		}
		for (r = pos.begin(); r != pos.end(); r++){
			comp[*r].insert(re);
			at[re].insert(*r);
		}
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) unicomp(2 * k + 1, nl, nm, l, r, v);
	if (r >= nm + 1) unicomp(2 * k + 2, nm + 1, nr, l, r, v);
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	FILL(ptl, -1);
	FILL(phd, -1);
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], find(id));
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			emn[id] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], id);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	assert(P < MAXP);
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], ncnt[MAXN], ecnt[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	ncnt[y] += ncnt[x];
	ecnt[y] += ecnt[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];
set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl==nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if(x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr){
		return val[k];
	}
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if(l<=nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if(r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
void ucomp(int k){
	set<int> ns;
	set<int>::iterator r;
	for (r = comp[k].begin(); r != comp[k].end(); r++) {
		ns.insert(find(*r));
	}
	comp[k] = ns;
}
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k].insert(v);
}
set<int> getcomp(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr){
		ucomp(k);
		return comp[k];
	}
	ucomp(k);
	int nm = (nl + nr) >> 1;
	set<int> s1, s2;
	if (l <= nm) s1 = getcomp(2 * k + 1, nl, nm, l, r);
	if (r> nm) s2 = getcomp(2 * k + 2, nm + 1, nr, l, r);
	s1.insert(s2.begin(), s2.end());
	return s1;
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		ucomp(k);
		comp[k].erase(v);
		return;
	}
	ucomp(k);
	int nm = (nl + nr) >> 1;
	bool gol = 0;
	if (x <= nm) {
		gol = 1;
		remcomp(2 * k + 1, nl, nm, x, v);
	} else remcomp(2 * k + 2, nm + 1, nr, x, v);
	if (gol && comp[2 * k + 2].find(v) == comp[2 * k + 2].end()) comp[k].erase(v);
	if (!gol && comp[2 * k + 1].find(v) == comp[2 * k + 1].end()) comp[k].erase(v);
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
		if (x[i][0] > x[i][1]) swap(x[i][0], x[i][1]);
		if (y[i][0] > y[i][1]) swap(y[i][0], y[i][1]);
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		} else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << endl;
		eve &e = es[i];
		int id = e.id;
		int rid = find(id);
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], rid);
		}else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], rid);
		}else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			int ninc = n, einc = n * 2;
			ncnt[rid] += ninc;
			ecnt[rid] += einc;
			set<int> comps = getcomp(0, 0, X - 1, x[id][0], x[id][1]);
			set<int>::iterator r;
			for (r = comps.begin(); r != comps.end(); r++) {
				unionset(*r, rid);
			}
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ncnt[j] += 2 * cnt[j];
			ecnt[j] += cnt[j];
			ll f = 2 + ecnt[j] - ncnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];

set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
int TOT;
set<int> at[MAXN];
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		at[v].insert(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k].insert(v);
	at[v].insert(k);
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].erase(v);
		at[v].erase(k);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) remcomp(2 * k + 1, nl, nm, x, v);
	else remcomp(2 * k + 2, nm + 1, nr, x, v);
	if (comp[2 * k + 1].find(v) == comp[2 * k + 1].end() && comp[2 * k + 2].find(v) == comp[2 * k + 2].end()){
		comp[k].erase(v);
		at[v].erase(k);
	}
}
int D, dod[MAXN];
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		set<int>::iterator r;
		D = 0;
		for (r = comp[k].begin(); r != comp[k].end(); r++) {
			unionset(*r, v);
			dod[D++] = *r;
		}
		int re = find(v);
		REP(i, 0, D){
			int x = dod[i];
			if (x == re) continue;
			for (r = at[x].begin(); r != at[x].end(); r++){
				comp[*r].erase(x);
				comp[*r].insert(re);
				at[re].insert(*r);
			}
			at[x].clear();
		}
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) unicomp(2 * k + 1, nl, nm, l, r, v);
	if (r >= nm + 1) unicomp(2 * k + 2, nm + 1, nr, l, r, v);
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], find(id));
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			emn[id] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], id);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXP 10000005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], emn[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	emn[y] += emn[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];
int P, pnxt[MAXP], pid[MAXP], psd[MAXP], ptl[MAXV], phd[MAXV];
int Q, markql[MAXN], markqr[MAXN];
int TOT;
void ip(int a, int b, int sd){
	TOT++;
	pid[P] = b;
	psd[P] = sd;
	pnxt[P] = -1;
	if (phd[a] == -1) ptl[a] = phd[a] = P;
	else {
		pnxt[ptl[a]] = P;
		ptl[a] = P;
	}
	P++;
}
void add(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr) return val[k];
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if (l <= nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if (r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
bool ucomp(int k, int v){
	int p = phd[k];
	while (p != -1){
		int id = pid[p];
		int rid = id > 0 ? find(id) : find(-id);
		int sd = psd[p];
		if (id < 0){	// remove
			if (sd == 0){
				markql[rid] = markqr[rid] = 0;
			} else if (sd == -1){
				markql[rid] = 0;
			} else if (sd == 1){
				markqr[rid] = 0;
			}
		}
		else {
			if (sd == 0){
				markql[rid] = markqr[rid] = Q;
			} else if (sd == -1){
				markql[rid] = Q;
			} else if (sd == 1){
				markqr[rid] = Q;
			}
		}
		p = pnxt[p];
	}
	p = phd[k];
	bool hit = 0;
	int cc = 0;
	while (p != -1){
		int id = pid[p];
		if (id < 0) id = -id;
		int rid = find(id);
		if (markql[rid] == Q || markqr[rid] == Q){
			//cerr << "u " << rid << " " << v << endl;
			cc++;
			hit = 1;
 			unionset(rid, v);
		}
		p = pnxt[p];
	}
	if (hit){
		ptl[k] = phd[k] = -1;
		int vid = find(v);
		ip(k, vid, 0);
	}
	return hit;
}
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		ip(k, v, 0);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) {
		addcomp(2 * k + 1, nl, nm, x, v);
		ip(k, v, -1);
	} else {
		addcomp(2 * k + 2, nm + 1, nr, x, v);
		ip(k, v, 1);
	}
}
void unicomp(int k, int nl, int nr, int l, int r, int v){
	if (l <= nl && r >= nr){
		ucomp(k, v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (l <= nm) {
		unicomp(2 * k + 1, nl, nm, l, r, v);
	}
	if (r >= nm + 1){
		unicomp(2 * k + 2, nm + 1, nr, l, r, v);
	}
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	FILL(ptl, -1);
	FILL(phd, -1);
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
		if (x[i][0] > x[i][1]) swap(x[i][0], x[i][1]);
		if (y[i][0] > y[i][1]) swap(y[i][0], y[i][1]);
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		}
		else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		//if (i % 1000 == 0) cerr << i << " " << TOT << endl;
		Q = i + 1;
		eve &e = es[i];
		int id = e.id;
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], id);
		}
		else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			addcomp(0, 0, X - 1, x[id][0], -id);
		}
		else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			int rid = find(id);
			emn[rid] += n;
			unicomp(0, 0, X - 1, x[id][0], x[id][1], rid);
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ll f = 2 + emn[j] - cnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <complex>
#include <ctime>
#include <cassert>

using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> PII;

#define REP(i,s,t) for(int i=(s);i<(t);i++)
#define FILL(x,v) memset(x,v,sizeof(x))

const int INF = (int)1E9;
#define MAXN 200005
#define MAXN2 (MAXN*2)

int N;
int xs[MAXN2], ys[MAXN2], X, Y;
int x[MAXN][2], y[MAXN][2];
int rnk[MAXN], rep[MAXN];
bool sv[MAXN];
ll sumlen[MAXN], ncnt[MAXN], ecnt[MAXN], cnt[MAXN];
int find(int k){
	if (rep[k] == k) return k;
	return rep[k] = find(rep[k]);
}
void unionset(int a, int b){
	int x = find(a), y = find(b);
	if (x == y) return;
	if (rnk[x]>rnk[y]) swap(x, y);
	if (rnk[x] == rnk[y]) rnk[y]++;
	rep[x] = y;
	sumlen[y] += sumlen[x];
	ncnt[y] += ncnt[x];
	ecnt[y] += ecnt[x];
	cnt[y] += cnt[x];
}

#define MAXV 1<<20
int val[MAXV], lz[MAXV];
set<int> comp[MAXV];
void add(int k, int nl, int nr, int x, int v){
	if (nl==nr) {
		val[k] += v;
		return;
	}
	int nm = (nl + nr) >> 1;
	if(x <= nm) add(2 * k + 1, nl, nm, x, v);
	else add(2 * k + 2, nm + 1, nr, x, v);
	val[k] = val[2 * k + 1] + val[2 * k + 2];
}

int get(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr){
		return val[k];
	}
	int nm = (nl + nr) >> 1;
	int a1 = 0, a2 = 0;
	if(l<=nm) a1 = get(2 * k + 1, nl, nm, l, r);
	if(r> nm) a2 = get(2 * k + 2, nm + 1, nr, l, r);
	return a1 + a2;
}
void ucomp(int k){
	set<int> ns;
	set<int>::iterator r;
	for (r = comp[k].begin(); r != comp[k].end(); r++) {
		ns.insert(find(*r));
	}
	comp[k] = ns;
}
void addcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		comp[k].insert(v);
		return;
	}
	int nm = (nl + nr) >> 1;
	if (x <= nm) addcomp(2 * k + 1, nl, nm, x, v);
	else addcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k] = comp[2 * k + 1];
	comp[k].insert(comp[2 * k + 2].begin(), comp[2 * k + 2].end());
}
set<int> getcomp(int k, int nl, int nr, int l, int r){
	if (l <= nl && r >= nr){
		ucomp(k);
		return comp[k];
	}
	ucomp(k);
	int nm = (nl + nr) >> 1;
	set<int> s1, s2;
	if (l <= nm) s1 = getcomp(2 * k + 1, nl, nm, l, r);
	if (r> nm) s2 = getcomp(2 * k + 2, nm + 1, nr, l, r);
	s1.insert(s2.begin(), s2.end());
	return s1;
}
void remcomp(int k, int nl, int nr, int x, int v){
	if (nl == nr) {
		ucomp(k);
		comp[k].erase(v);
		return;
	}
	ucomp(k);
	int nm = (nl + nr) >> 1;
	if (x <= nm) remcomp(2 * k + 1, nl, nm, x, v);
	else remcomp(2 * k + 2, nm + 1, nr, x, v);
	comp[k] = comp[2 * k + 1];
	comp[k].insert(comp[2 * k + 2].begin(), comp[2 * k + 2].end());
}

int E;
struct eve {
	int tp, id, y;
	// 0: begin vert, 1: hori, 2: end vert
	eve(){}
	eve(int _tp, int _id, int _y){
		tp = _tp;
		id = _id;
		y = _y;
	}
	bool operator < (const eve &ano) const {
		if (y == ano.y) return tp < ano.tp;
		return y < ano.y;
	}
} es[MAXN2];

int main(){
	cin >> N;
	REP(i, 0, N){
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		xs[X++] = x1; xs[X++] = x2;
		ys[Y++] = y1; ys[Y++] = y2;
		x[i][0] = x1; x[i][1] = x2;
		y[i][0] = y1; y[i][1] = y2;
	}
	sort(xs, xs + X);
	X = unique(xs, xs + X) - xs;
	sort(ys, ys + Y);
	Y = unique(ys, ys + Y) - ys;
	REP(i, 0, N){
		x[i][0] = lower_bound(xs, xs + X, x[i][0]) - xs;
		x[i][1] = lower_bound(xs, xs + X, x[i][1]) - xs;
		y[i][0] = lower_bound(ys, ys + Y, y[i][0]) - ys;
		y[i][1] = lower_bound(ys, ys + Y, y[i][1]) - ys;
		if (x[i][0] > x[i][1]) swap(x[i][0], x[i][1]);
		if (y[i][0] > y[i][1]) swap(y[i][0], y[i][1]);
	}
	REP(i, 0, N){
		rnk[i] = 0;
		rep[i] = i;
		cnt[i] = 1;
		sumlen[i] = (ll)(ys[y[i][1]] - ys[y[i][0]]) + (ll)(xs[x[i][1]] - xs[x[i][0]]);
	}
	REP(i, 0, N){
		if (x[i][0] == x[i][1]){	// vert
			es[E++] = eve(0, i, y[i][0]);
			es[E++] = eve(2, i, y[i][1]);
		} else { // hori
			es[E++] = eve(1, i, y[i][0]);
		}
	}
	sort(es, es + E);
	REP(i, 0, E){
		eve &e = es[i];
		int id = e.id;
		int rid = find(id);
		if (e.tp == 0){
			add(0, 0, X - 1, x[id][0], 1);
			addcomp(0, 0, X - 1, x[id][0], rid);
		}else if (e.tp == 2){
			add(0, 0, X - 1, x[id][0], -1);
			remcomp(0, 0, X - 1, x[id][0], rid);
		}else{
			int n = get(0, 0, X - 1, x[id][0], x[id][1]);
			int ninc = n, einc = n * 2;
			ncnt[rid] += ninc;
			ecnt[rid] += einc;
			set<int> comps = getcomp(0, 0, X - 1, x[id][0], x[id][1]);
			set<int>::iterator r;
			for (r = comps.begin(); r != comps.end(); r++) {
				unionset(*r, rid);
			}
		}
	}
	ll ans = 0;
	REP(i, 0, N){
		int j = find(i);
		if (!sv[j]){
			sv[j] = 1;
			ncnt[j] += 2 * cnt[j];
			ecnt[j] += cnt[j];
			ll f = 2 + ecnt[j] - ncnt[j];
			ll sol = sumlen[j] - (f - 1);
			ans = max(ans, sol);
		}
	}
	cout << ans << endl;
	return 0;
}