#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

int pcnt[100];

typedef struct IN {
	int n;
	int x1[200000],y1[200000],x2[200000],y2[200000];
	void read() {
		scanf("%d",&n);
		REP(i,n) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
	}
	void gen() {
		srand(time(NULL));
		int each=100000; n=2*each;
		REP(i,each) x1[i]=x2[i]=i,y1[i]=rand()%100000,y2[i]=y1[i]+rand()%100000;
		REP(i,each) x1[each+i]=rand()%100000,x2[each+i]=x1[each+i]+rand()%100000,y1[each+i]=y2[each+i]=i;
	}
} IN;
IN in;
bool debug=false;
typedef struct UF {
	int par[200000];
	int rnk[200000];
	ll len[200000];

	int q[200000],nq;

	void create(int a,int nlen) {
		par[a]=a; rnk[a]=0; len[a]=nlen;
	}
	int find(int a) {
		//if(debug) printf("find(%d): %d/%lld\n",a,par[a],len[a]);
		nq=0;
		while(par[a]!=a) {
			q[nq++]=a;
			a=par[a];
		}
		REP(i,nq) par[q[i]]=a;
		return a;
	}
	void unite(int a,int b) {
		++pcnt[1];
		a=find(a); b=find(b);
		if(a==b) { --len[a]; return; }
		if(rnk[a]<rnk[b]) swap(a,b);
		par[b]=a; len[a]+=len[b];
	}
	void reduce(int a,int by) {
		++pcnt[2];
		a=find(a); len[a]-=by;
	}
} UF;
UF uf;

typedef struct Y {
	int val,cnt;
	int p; int c[2];
} Y;

typedef struct YT {
	Y y[200000]; int ny;
	YT() { ny=0; }
	void calc(int a) {
		y[a].cnt=1+(y[a].c[0]!=-1?y[y[a].c[0]].cnt:0)+(y[a].c[1]!=-1?y[y[a].c[1]].cnt:0);
	}
	int childindex(int a,int b) {
		assert(a!=-1);
		assert(b!=-1);
		if(y[a].c[0]==b) return 0;
		if(y[a].c[1]==b) return 1;
		assert(false);
		return -1;
	}
	void rotate(int a,int ai) {
		++pcnt[3];
		int b=y[a].c[ai];
		assert(a!=-1);
		assert(b!=-1);
		y[b].p=y[a].p; if(y[b].p!=-1) { y[y[b].p].c[childindex(y[b].p,a)]=b; }
		y[a].c[ai]=y[b].c[1-ai]; if(y[a].c[ai]!=-1) y[y[a].c[ai]].p=a;
		y[b].c[1-ai]=a; y[a].p=b;
		calc(a); calc(b);
	}
	int splay(int a) {
		++pcnt[4];
		assert(a!=-1);
		while(y[a].p!=-1) {
			++pcnt[5];
			int b=y[a].p,bi=childindex(b,a);
			if(y[b].p==-1) { rotate(b,bi); continue; }
			int c=y[b].p,ci=childindex(c,b);
			if(bi==ci) { rotate(c,ci); rotate(b,bi); }
			else { rotate(b,bi); rotate(c,ci); }
		}
		return a;
	}
	int connect(int lyid,int ryid) {
		if(ryid==-1) return lyid;
		if(lyid==-1) return ryid;
		lyid=getlast(lyid); ryid=splay(ryid);
		y[lyid].c[1]=ryid; y[ryid].p=lyid; calc(lyid);
		return lyid;
	}
	int connect(int lyid,int myid,int ryid) {
		return connect(connect(lyid,myid),ryid);
	}
	void disconnect(int lyid,int &ryid) {
		lyid=splay(lyid);
		ryid=y[lyid].c[1];
		if(ryid!=-1) {
			y[lyid].c[1]=y[ryid].p=-1;
			calc(lyid);
		}
	}
	void split(int yid,int &lyid,int &hyid,int val) {
		if(yid==-1) { lyid=hyid=-1; return; }
		yid=splay(yid);
		lyid=-1; int pyid=yid;
		for(int cyid=yid;cyid!=-1;) {
			++pcnt[15]; pyid=cyid;
			if(y[cyid].val<val) {
				lyid=cyid;
				cyid=y[cyid].c[1];
			} else {
				cyid=y[cyid].c[0];
			}
		}
		if(pyid!=-1) yid=splay(pyid);
		if(lyid!=-1) disconnect(lyid,hyid); else hyid=yid;
	}

	void split(int yid,int &lyid,int &myid,int &hyid,int val) {
		split(yid,lyid,yid,val);
		split(yid,myid,hyid,val+1);
	}
	int removerange(int &yid,int lval,int hval) {
		int lyid,hyid,ryid=yid;
		split(ryid,lyid,ryid,lval);
		split(ryid,ryid,hyid,hval+1);
		yid=connect(lyid,hyid);
		return ryid;
	}
	int getfirst(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[0]!=-1) {
			++pcnt[6];
			yid=y[yid].c[0];
		}
		return splay(yid);
	}
	int getlast(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[1]!=-1) {
			++pcnt[7];
			yid=y[yid].c[1];
		}
		return splay(yid);
	}
	bool check(int yid,int &py) {
		if(y[yid].c[0]!=-1&&!check(y[yid].c[0],py)) return false;
		if(y[yid].val<=py) { printf("yerror: not strictly increasing at %d (prev=%d mine=%d)\n",yid,py,y[yid].val); return false; }
		if(y[yid].c[1]!=-1&&!check(y[yid].c[1],py)) return false;
		return true;
	}
	void print(int yid) {
		if(yid==-1) { printf("-"); return; }
		printf("["); print(y[yid].c[0]); printf("%d",y[yid].val); print(y[yid].c[1]); printf("]");
	}
} YT;
YT yt;

typedef struct B {
	int ly,hy,yid,ufid;
	int p; int c[2];
} B;

typedef struct BT {
	B b[200000]; int nb;
	int bid;
	BT() { nb=0; bid=-1; }
	int childindex(int x,int y) {
		assert(x!=-1);
		assert(y!=-1);
		if(b[x].c[0]==y) return 0;
		if(b[x].c[1]==y) return 1;
		assert(false);
		return -1;
	}
	void rotate(int x,int xi) {
			++pcnt[8];
		int y=b[x].c[xi];
		assert(x!=-1);
		assert(y!=-1);
		b[y].p=b[x].p; if(b[y].p!=-1) { b[b[y].p].c[childindex(b[y].p,x)]=y; }
		b[x].c[xi]=b[y].c[1-xi]; if(b[x].c[xi]!=-1) b[b[x].c[xi]].p=x;
		b[y].c[1-xi]=x; b[x].p=y;
	}
	int splay(int x) {
			++pcnt[9];
		assert(x!=-1);
		while(b[x].p!=-1) {
			++pcnt[10];
			int y=b[x].p,yi=childindex(y,x);
			if(b[y].p==-1) { rotate(y,yi); continue; }
			int z=b[y].p,zi=childindex(z,y);
			if(yi==zi) { rotate(z,zi); rotate(y,yi); }
			else { rotate(y,yi); rotate(z,zi); }
		}
		return x;
	}
	void disconnect(int lbid,int &rbid) {
		lbid=splay(lbid);
		rbid=b[lbid].c[1];
		if(rbid!=-1) b[lbid].c[1]=b[rbid].p=-1;
	}
	int connect(int lbid,int rbid) {
		if(rbid==-1) return lbid;
		if(lbid==-1) return rbid;
		lbid=getlast(lbid); rbid=splay(rbid);
		b[lbid].c[1]=rbid; b[rbid].p=lbid; return lbid;
	}
	void splitly(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[16]; pbid=cbid;
			if(b[cbid].ly<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}
	void splithy(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[17]; pbid=cbid;
			if(b[cbid].hy<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}

	int removerange(int ly,int hy) {
		int lbid,hbid,rbid=bid;
		splithy(rbid,lbid,rbid,ly); // all b with b.hy < ly
		splitly(rbid,rbid,hbid,hy+1); // all b with b.ly <= hy
		bid=connect(lbid,hbid);
		return rbid;
	}
	void insert(int nbid) {
		//printf("inserting %d\n",nbid);
		//printroot();
		int lbid,hbid;
		splitly(bid,lbid,hbid,b[nbid].ly);
		//printf("%d %d\n",lbid,hbid);
		bid=connect(connect(lbid,nbid),hbid);
		//printf("->\n");
		//printroot();
	}
	int getfirst(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[0]!=-1) {
			++pcnt[11];
			bid=b[bid].c[0];
		}
		return splay(bid);
	}
	int getlast(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[1]!=-1) {
			++pcnt[12];
			bid=b[bid].c[1];
		}
		return splay(bid);
	}
	bool checkroot() {
		if(bid==-1) return true;
		bid=splay(bid);
		int py=INT_MIN; return check(bid,py);
	}
	bool check(int bid,int &py) {
		if(b[bid].c[0]!=-1&&!check(b[bid].c[0],py)) return false;
		if(b[bid].ly<=py) { printf("error: ranges overlap. bid=%d, ly=%d, py=%d\n",bid,b[bid].ly,py); return false; }
		py=b[bid].hy;
		int npy=INT_MIN; if(!yt.check(yt.splay(b[bid].yid),npy)) return false;
		int ly=yt.y[yt.getfirst(b[bid].yid)].val,hy=yt.y[yt.getlast(b[bid].yid)].val;
		if(b[bid].ly!=ly) { printf("error: minimum not same at bid=%d (have %d want %d)\n",bid,b[bid].ly,ly); return false; }
		if(b[bid].hy!=hy) { printf("error: maximum not same at bid=%d (have %d want %d)\n",bid,b[bid].hy,hy); return false; }
		if(b[bid].c[1]!=-1&&!check(b[bid].c[1],py)) return false;
		return true;
	}
	void printroot() {
		if(bid==-1) { printf("empty\n"); return; }
		bid=splay(bid);
		print(bid,0);
	}
	void print(int bid,int d) {
		if(bid==-1) return;
		print(b[bid].c[0],d+1);
		REP(i,d) printf("  "); printf("%d: [%d..%d] cnt=%d uf=%d ",bid,b[bid].ly,b[bid].hy,yt.y[yt.splay(b[bid].yid)].cnt,b[bid].ufid); yt.print(b[bid].yid); puts("");
		print(b[bid].c[1],d+1);
	}
} BT;
BT bt;

typedef struct E {
	int type; // 0=shor,1=vrt,2=thor
	int id;
} E;
bool operator<(const E &a,const E &b) {
	int ax=a.type==1?in.x1[a.id]:a.type==0?in.x1[a.id]:in.x2[a.id];
	int bx=b.type==1?in.x1[b.id]:b.type==0?in.x1[b.id]:in.x2[b.id];
	if(ax!=bx) return ax<bx;
	if(a.type!=b.type) return a.type<b.type;
	return in.y1[a.id]<in.y1[b.id];
}

typedef struct ELST {
	E e[400000]; int ne;
	void init() {
		ne=0;
		REP(i,in.n) if(in.x1[i]==in.x2[i]) {
			e[ne].type=1; e[ne].id=i; ++ne;
		} else if(in.y1[i]==in.y2[i]) {
			e[ne].type=0; e[ne].id=i; ++ne;
			e[ne].type=2; e[ne].id=i; ++ne;
		} else {
			assert(false);
		}
		sort(e,e+ne);
	}
	void process() {
		REP(i,in.n) uf.create(i,in.x2[i]-in.x1[i]+in.y2[i]-in.y1[i]);
		REP(ei,ne) {
			++pcnt[13];
			int id=e[ei].id;
			//if(!bt.checkroot()) { bt.printroot(); exit(0); }
			//bt.printroot();
			//printf("processing %d (type=%d)\n",id,e[ei].type);
			if(e[ei].type==0) {
				// create a new block
				// insert block into BT (possibly splitting existing block)
				int yid=yt.ny++;
				Y &y=yt.y[yid];
				y.p=-1,y.c[0]=-1,y.c[1]=-1,y.val=in.y1[id],y.cnt=1;
				int bid=bt.nb++;
				B &b=bt.b[bid];
				b.p=-1,b.c[0]=-1,b.c[1]=-1,b.ly=y.val,b.hy=y.val,b.ufid=id,b.yid=yid;
				int obid=bt.removerange(y.val,y.val);
				if(obid==-1) {
					bt.insert(bid);
				} else {
					B &ob=bt.b[obid];
					assert(ob.p==-1&&ob.c[0]==-1&&ob.c[1]==-1);
					int loyid,moyid,hoyid;
					yt.split(ob.yid,loyid,moyid,hoyid,y.val);
					assert(loyid!=-1&&moyid==-1&&hoyid!=-1);
					int nbid=bt.nb++;
					B &nb=bt.b[nbid];
					nb.p=-1,nb.c[0]=-1,nb.c[1]=-1,nb.ly=yt.y[yt.getfirst(hoyid)].val,nb.hy=ob.hy,nb.ufid=ob.ufid,nb.yid=hoyid;
					ob.hy=yt.y[yt.getlast(loyid)].val,ob.yid=loyid;
					bt.insert(obid); bt.insert(bid); bt.insert(nbid);
				}
			} else if(e[ei].type==2) {
				// find block
				// remove from block
				// if block is empty, remove from BT
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				assert(bid!=-1);
				B &b=bt.b[bid];
				assert(b.p==-1&&b.c[0]==-1&&b.c[1]==-1);
				int yid=yt.removerange(b.yid,in.y1[id],in.y2[id]);
				//printf("remove yid(%d,%d,%d) [%d]: ",b.yid,in.y1[id],in.y2[id],b.yid); yt.print(yid); printf("\n");
				assert(yid!=-1);
				Y &y=yt.y[yid];
				assert(y.p==-1&&y.c[0]==-1&&y.c[1]==-1);
				if(b.yid!=-1) {
					b.ly=yt.y[yt.getfirst(b.yid)].val;
					b.hy=yt.y[yt.getlast(b.yid)].val;
					bt.insert(bid);
				}
			} else if(e[ei].type==1) {
				// find blocks and merge them:
				// o merge B
				// o merge YT
				// o remove one from BT
				// o merge in UF
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				//printf("removed:\n"); bt.print(bt.splay(bid),0);
				//printf("remaining:\n"); bt.printroot();
				if(bid==-1) continue;
				uf.unite(id,bt.b[bid].ufid);
				reduceinblock(bid,in.y1[id],in.y2[id]);
				//printf("united\n");
				while(true) {
			++pcnt[14];
					bid=bt.getfirst(bid);
					//printf("first=%d\n",bid);
					B &b=bt.b[bid];
					int nbid=b.c[1];
					if(nbid==-1) break;
					reduceinblock(nbid,in.y1[id],in.y2[id]);
					b.c[1]=-1; bt.b[nbid].p=-1; nbid=bt.getfirst(nbid);
					B &nb=bt.b[nbid];
					//printf("merging %d and %d\n",bid,nbid);
					nb.ly=b.ly;
					int yid=yt.splay(b.yid),nyid=yt.getfirst(nb.yid);
					Y &ny=yt.y[nyid];
					Y &y=yt.y[yid];
					ny.c[0]=yid; y.p=nyid; yt.calc(nyid);
					int ufid=b.ufid,nufid=nb.ufid;
					uf.unite(ufid,nufid);
					bid=nbid;
				}
				bt.insert(bid);
			}
		}
	}

	void reduceinblock(int bid,int y1,int y2) {
		B &b=bt.b[bid];
		int lyid,hyid,ryid=b.yid;
		yt.split(ryid,lyid,ryid,y1);
		yt.split(ryid,ryid,hyid,y2+1);
		if(ryid!=-1) {
			int cnt=yt.y[yt.splay(ryid)].cnt;
			//printf("cnt=%d\n",cnt);
			uf.reduce(b.ufid,cnt-1);
		}
		b.yid=yt.connect(lyid,ryid,hyid);
	}
} ELST;
ELST elst;

void run() {
	in.read();
	//in.gen();
	elst.init();
	elst.process();
	ll ret=0;
	debug=true;
	REP(i,in.n) {
		if(uf.find(i)==i) {
			ll cur=uf.len[i];
			if(cur>ret) ret=cur;
		}
	}
	cout<<ret<<endl;
/*	REP(i,18) fprintf(stderr,"p%d: %d\n",i,pcnt[i]);
	fprintf(stderr,"n: %d\n",in.n);
	fprintf(stderr,"ny: %d\n",yt.ny);
	fprintf(stderr,"nb: %d\n",bt.nb);
	fprintf(stderr,"ne: %d\n",elst.ne); */
}

int main() {
	run();
	return 0;
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

int pcnt[100];

typedef struct IN {
	int n;
	int x1[200000],y1[200000],x2[200000],y2[200000];
	void read() {
		scanf("%d",&n);
		REP(i,n) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
	}
	void gen() {
		int each=100000; n=2*each;
		REP(i,each) x1[i]=x2[i]=i,y1[i]=0,y2[i]=each-1;
		REP(i,each) x1[each+i]=0,x2[each+i]=each-1,y1[each+i]=y2[each+i]=i;
	}
} IN;
IN in;
bool debug=false;
typedef struct UF {
	int par[200000];
	int rnk[200000];
	ll len[200000];

	int q[200000],nq;

	void create(int a,int nlen) {
		par[a]=a; rnk[a]=0; len[a]=nlen;
	}
	int find(int a) {
		//if(debug) printf("find(%d): %d/%lld\n",a,par[a],len[a]);
		nq=0;
		while(par[a]!=a) {
			q[nq++]=a;
			a=par[a];
		}
		REP(i,nq) par[q[i]]=a;
		return a;
	}
	void unite(int a,int b) {
		++pcnt[1];
		a=find(a); b=find(b);
		if(a==b) { --len[a]; return; }
		if(rnk[a]<rnk[b]) swap(a,b);
		par[b]=a; len[a]+=len[b];
	}
	void reduce(int a,int by) {
		++pcnt[2];
		a=find(a); len[a]-=by;
	}
} UF;
UF uf;

typedef struct Y {
	int val,cnt;
	int p; int c[2];
} Y;

typedef struct YT {
	Y y[200000]; int ny;
	YT() { ny=0; }
	void calc(int a) {
		y[a].cnt=1+(y[a].c[0]!=-1?y[y[a].c[0]].cnt:0)+(y[a].c[1]!=-1?y[y[a].c[1]].cnt:0);
	}
	int childindex(int a,int b) {
		assert(a!=-1);
		assert(b!=-1);
		if(y[a].c[0]==b) return 0;
		if(y[a].c[1]==b) return 1;
		assert(false);
		return -1;
	}
	void rotate(int a,int ai) {
		++pcnt[3];
		int b=y[a].c[ai];
		assert(a!=-1);
		assert(b!=-1);
		y[b].p=y[a].p; if(y[b].p!=-1) { y[y[b].p].c[childindex(y[b].p,a)]=b; }
		y[a].c[ai]=y[b].c[1-ai]; if(y[a].c[ai]!=-1) y[y[a].c[ai]].p=a;
		y[b].c[1-ai]=a; y[a].p=b;
		calc(a); calc(b);
	}
	int splay(int a) {
		++pcnt[4];
		assert(a!=-1);
		while(y[a].p!=-1) {
			++pcnt[5];
			int b=y[a].p,bi=childindex(b,a);
			if(y[b].p==-1) { rotate(b,bi); continue; }
			int c=y[b].p,ci=childindex(c,b);
			if(bi==ci) { rotate(c,ci); rotate(b,bi); }
			else { rotate(b,bi); rotate(c,ci); }
		}
		return a;
	}
	int connect(int lyid,int ryid) {
		if(ryid==-1) return lyid;
		if(lyid==-1) return ryid;
		lyid=getlast(lyid); ryid=splay(ryid);
		y[lyid].c[1]=ryid; y[ryid].p=lyid; calc(lyid);
		return lyid;
	}
	int connect(int lyid,int myid,int ryid) {
		return connect(connect(lyid,myid),ryid);
	}
	void disconnect(int lyid,int &ryid) {
		lyid=splay(lyid);
		ryid=y[lyid].c[1];
		if(ryid!=-1) {
			y[lyid].c[1]=y[ryid].p=-1;
			calc(lyid);
		}
	}
	void split(int yid,int &lyid,int &hyid,int val) {
		if(yid==-1) { lyid=hyid=-1; return; }
		yid=splay(yid);
		lyid=-1; int pyid=yid;
		for(int cyid=yid;cyid!=-1;) {
			++pcnt[15]; pyid=cyid;
			if(y[cyid].val<val) {
				lyid=cyid;
				cyid=y[cyid].c[1];
			} else {
				cyid=y[cyid].c[0];
			}
		}
		if(pyid!=-1) yid=splay(pyid);
		if(lyid!=-1) disconnect(lyid,hyid); else hyid=yid;
	}

	void split(int yid,int &lyid,int &myid,int &hyid,int val) {
		split(yid,lyid,yid,val);
		split(yid,myid,hyid,val+1);
	}
	int removerange(int &yid,int lval,int hval) {
		int lyid,hyid,ryid=yid;
		split(ryid,lyid,ryid,lval);
		split(ryid,ryid,hyid,hval+1);
		yid=connect(lyid,hyid);
		return ryid;
	}
	int getfirst(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[0]!=-1) {
			++pcnt[6];
			yid=y[yid].c[0];
		}
		return splay(yid);
	}
	int getlast(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[1]!=-1) {
			++pcnt[7];
			yid=y[yid].c[1];
		}
		return splay(yid);
	}
	void print(int yid) {
		if(yid==-1) { printf("-"); return; }
		printf("["); print(y[yid].c[0]); printf("%d",y[yid].val); print(y[yid].c[1]); printf("]");
	}
} YT;
YT yt;

typedef struct B {
	int ly,hy,yid,ufid;
	int p; int c[2];
} B;

typedef struct BT {
	B b[200000]; int nb;
	int bid;
	BT() { nb=0; bid=-1; }
	int childindex(int x,int y) {
		assert(x!=-1);
		assert(y!=-1);
		if(b[x].c[0]==y) return 0;
		if(b[x].c[1]==y) return 1;
		assert(false);
		return -1;
	}
	void rotate(int x,int xi) {
			++pcnt[8];
		int y=b[x].c[xi];
		assert(x!=-1);
		assert(y!=-1);
		b[y].p=b[x].p; if(b[y].p!=-1) { b[b[y].p].c[childindex(b[y].p,x)]=y; }
		b[x].c[xi]=b[y].c[1-xi]; if(b[x].c[xi]!=-1) b[b[x].c[xi]].p=x;
		b[y].c[1-xi]=x; b[x].p=y;
	}
	int splay(int x) {
			++pcnt[9];
		assert(x!=-1);
		while(b[x].p!=-1) {
			++pcnt[10];
			int y=b[x].p,yi=childindex(y,x);
			if(b[y].p==-1) { rotate(y,yi); continue; }
			int z=b[y].p,zi=childindex(z,y);
			if(yi==zi) { rotate(z,zi); rotate(y,yi); }
			else { rotate(y,yi); rotate(z,zi); }
		}
		return x;
	}
	void disconnect(int lbid,int &rbid) {
		lbid=splay(lbid);
		rbid=b[lbid].c[1];
		if(rbid!=-1) b[lbid].c[1]=b[rbid].p=-1;
	}
	int connect(int lbid,int rbid) {
		if(rbid==-1) return lbid;
		if(lbid==-1) return rbid;
		lbid=getlast(lbid); rbid=splay(rbid);
		b[lbid].c[1]=rbid; b[rbid].p=lbid; return lbid;
	}
	void splitly(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[16]; pbid=cbid;
			if(b[cbid].ly<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}
	void splithy(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[17]; pbid=cbid;
			if(b[cbid].hy<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}

	int removerange(int ly,int hy) {
		int lbid,hbid,rbid=bid;
		splithy(rbid,lbid,rbid,ly); // all b with b.hy < ly
		splitly(rbid,rbid,hbid,hy+1); // all b with b.ly <= hy
		bid=connect(lbid,hbid);
		return rbid;
	}
	void insert(int nbid) {
		//printf("inserting %d\n",nbid);
		//printroot();
		int lbid,hbid;
		splitly(bid,lbid,hbid,b[nbid].ly);
		//printf("%d %d\n",lbid,hbid);
		bid=connect(connect(lbid,nbid),hbid);
		//printf("->\n");
		//printroot();
	}
	int getfirst(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[0]!=-1) {
			++pcnt[11];
			bid=b[bid].c[0];
		}
		return splay(bid);
	}
	int getlast(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[1]!=-1) {
			++pcnt[12];
			bid=b[bid].c[1];
		}
		return splay(bid);
	}
	void printroot() {
		if(bid==-1) { printf("empty\n"); return; }
		bid=splay(bid);
		print(bid,0);
	}
	void print(int bid,int d) {
		if(bid==-1) return;
		print(b[bid].c[0],d+1);
		REP(i,d) printf("  "); printf("%d: [%d..%d] cnt=%d uf=%d ",bid,b[bid].ly,b[bid].hy,yt.y[yt.splay(b[bid].yid)].cnt,b[bid].ufid); yt.print(b[bid].yid); puts("");
		print(b[bid].c[1],d+1);
	}
} BT;
BT bt;

typedef struct E {
	int type; // 0=shor,1=vrt,2=thor
	int id;
} E;
bool operator<(const E &a,const E &b) {
	int ax=a.type==1?in.x1[a.id]:a.type==0?in.x1[a.id]:in.x2[a.id];
	int bx=b.type==1?in.x1[b.id]:b.type==0?in.x1[b.id]:in.x2[b.id];
	if(ax!=bx) return ax<bx;
	if(a.type!=b.type) return a.type<b.type;
	return in.y1[a.id]<in.y1[b.id];
}

typedef struct ELST {
	E e[400000]; int ne;
	void init() {
		ne=0;
		REP(i,in.n) if(in.x1[i]==in.x2[i]) {
			e[ne].type=1; e[ne].id=i; ++ne;
		} else if(in.y1[i]==in.y2[i]) {
			e[ne].type=0; e[ne].id=i; ++ne;
			e[ne].type=2; e[ne].id=i; ++ne;
		} else {
			assert(false);
		}
		sort(e,e+ne);
	}
	void process() {
		REP(i,in.n) uf.create(i,in.x2[i]-in.x1[i]+in.y2[i]-in.y1[i]);
		REP(ei,ne) {
			++pcnt[13];
			int id=e[ei].id;
			//bt.printroot();
			//printf("processing %d (type=%d)\n",id,e[ei].type);
			if(e[ei].type==0) {
				// create a new block
				// insert block into BT (possibly splitting existing block)
				int yid=yt.ny++;
				Y &y=yt.y[yid];
				y.p=-1,y.c[0]=-1,y.c[1]=-1,y.val=in.y1[id],y.cnt=1;
				int bid=bt.nb++;
				B &b=bt.b[bid];
				b.p=-1,b.c[0]=-1,b.c[1]=-1,b.ly=y.val,b.hy=y.val,b.ufid=id,b.yid=yid;
				int obid=bt.removerange(y.val,y.val);
				if(obid==-1) {
					bt.insert(bid);
				} else {
					B &ob=bt.b[obid];
					assert(ob.p==-1&&ob.c[0]==-1&&ob.c[1]==-1);
					int loyid,moyid,hoyid;
					yt.split(ob.yid,loyid,moyid,hoyid,y.val);
					assert(loyid!=-1&&moyid==-1&&hoyid!=-1);
					int nbid=bt.nb++;
					B &nb=bt.b[nbid];
					nb.p=-1,nb.c[0]=-1,nb.c[1]=-1,nb.ly=yt.y[yt.getfirst(hoyid)].val,nb.hy=ob.hy,nb.ufid=ob.ufid,nb.yid=hoyid;
					ob.hy=yt.y[yt.getlast(loyid)].val,ob.yid=loyid;
					bt.insert(obid); bt.insert(bid); bt.insert(nbid);
				}
			} else if(e[ei].type==2) {
				// find block
				// remove from block
				// if block is empty, remove from BT
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				assert(bid!=-1);
				B &b=bt.b[bid];
				assert(b.p==-1&&b.c[0]==-1&&b.c[1]==-1);
				int yid=yt.removerange(b.yid,in.y1[id],in.y2[id]);
				//printf("remove yid(%d,%d,%d) [%d]: ",b.yid,in.y1[id],in.y2[id],b.yid); yt.print(yid); printf("\n");
				assert(yid!=-1);
				Y &y=yt.y[yid];
				assert(y.p==-1&&y.c[0]==-1&&y.c[1]==-1);
				if(b.yid!=-1) {
					b.ly=yt.y[yt.getfirst(b.yid)].val;
					b.hy=yt.y[yt.getlast(b.yid)].val;
					bt.insert(bid);
				}
			} else if(e[ei].type==1) {
				// find blocks and merge them:
				// o merge B
				// o merge YT
				// o remove one from BT
				// o merge in UF
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				//printf("removed:\n"); bt.print(bt.splay(bid),0);
				//printf("remaining:\n"); bt.printroot();
				if(bid==-1) continue;
				uf.unite(id,bt.b[bid].ufid);
				reduceinblock(bid,in.y1[id],in.y2[id]);
				//printf("united\n");
				while(true) {
			++pcnt[14];
					bid=bt.getfirst(bid);
					//printf("first=%d\n",bid);
					B &b=bt.b[bid];
					int nbid=b.c[1];
					if(nbid==-1) break;
					reduceinblock(nbid,in.y1[id],in.y2[id]);
					b.c[1]=-1; bt.b[nbid].p=-1; nbid=bt.getfirst(nbid);
					B &nb=bt.b[nbid];
					//printf("merging %d and %d\n",bid,nbid);
					nb.ly=b.ly;
					int yid=yt.splay(b.yid),nyid=yt.getfirst(nb.yid);
					Y &ny=yt.y[nyid];
					Y &y=yt.y[yid];
					ny.c[0]=yid; y.p=nyid; yt.calc(nyid);
					int ufid=b.ufid,nufid=nb.ufid;
					uf.unite(ufid,nufid);
					bid=nbid;
				}
				bt.insert(bid);
			}
		}
	}

	void reduceinblock(int bid,int y1,int y2) {
		B &b=bt.b[bid];
		int lyid,hyid,ryid=b.yid;
		yt.split(ryid,lyid,ryid,y1);
		yt.split(ryid,ryid,hyid,y2+1);
		assert(ryid!=-1);
		int cnt=yt.y[yt.splay(ryid)].cnt;
		//printf("cnt=%d\n",cnt);
		uf.reduce(b.ufid,cnt-1);
		b.yid=yt.connect(lyid,ryid,hyid);
	}
} ELST;
ELST elst;

void run() {
	//in.read();
	in.gen();
	elst.init();
	elst.process();
	ll ret=0;
	debug=true;
	REP(i,in.n) {
		if(uf.find(i)==i) {
			ll cur=uf.len[i];
			if(cur>ret) ret=cur;
		}
	}
	cout<<ret<<endl;
	REP(i,18) fprintf(stderr,"p%d: %d\n",i,pcnt[i]);
	fprintf(stderr,"n: %d\n",in.n);
	fprintf(stderr,"ny: %d\n",yt.ny);
	fprintf(stderr,"nb: %d\n",bt.nb);
	fprintf(stderr,"ne: %d\n",elst.ne);
}

int main() {
	run();
	return 0;
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

typedef struct IN {
	int n;
	int x1[200000],y1[200000],x2[200000],y2[200000];
	void read() {
		scanf("%d",&n);
		REP(i,n) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
	}
} IN;
IN in;

typedef struct UF {
	int par[200000];
	int rnk[200000];
	int len[200000];

	void create(int a,int nlen) {
		par[a]=a; rnk[a]=0; len[a]=nlen;
	}
	int find(int a) {
		if(par[a]==a) return a;
		return par[a]=find(par[a]);
	}
	void unite(int a,int b) {
		a=find(a); b=find(b);
		if(a==b) { --len[a]; return; }
		if(rnk[a]<rnk[b]) swap(a,b);
		par[b]=a; len[a]+=len[b];
	}
	void reduce(int a,int by) {
		a=find(a); len[a]-=by;
	}
} UF;
UF uf;

typedef struct Y {
	int val,cnt;
	int p; int c[2];
} Y;

typedef struct YT {
	Y y[200000]; int ny;
	YT() { ny=0; }
	void calc(int a) {
		y[a].cnt=1+(y[a].c[0]!=-1?y[y[a].c[0]].cnt:0)+(y[a].c[1]!=-1?y[y[a].c[1]].cnt:0);
	}
	int childindex(int a,int b) {
		assert(a!=-1);
		assert(b!=-1);
		if(y[a].c[0]==b) return 0;
		if(y[a].c[1]==b) return 1;
		assert(false);
		return -1;
	}
	void rotate(int a,int ai) {
		int b=y[a].c[ai];
		assert(a!=-1);
		assert(b!=-1);
		y[b].p=y[a].p; if(y[b].p!=-1) { y[y[b].p].c[childindex(y[b].p,a)]=b; }
		y[a].c[ai]=y[b].c[1-ai]; if(y[a].c[ai]!=-1) y[y[a].c[ai]].p=a;
		y[b].c[1-ai]=a; y[a].p=b;
		calc(a); calc(b);
	}
	int splay(int a) {
		assert(a!=-1);
		while(y[a].p!=-1) {
			int b=y[a].p,bi=childindex(b,a);
			if(y[b].p==-1) { rotate(b,bi); continue; }
			int c=y[b].p,ci=childindex(c,b);
			if(bi==ci) { rotate(c,ci); rotate(b,bi); }
			else { rotate(b,bi); rotate(c,ci); }
		}
		return a;
	}
	int connect(int lyid,int ryid) {
		if(ryid==-1) return lyid;
		if(lyid==-1) return ryid;
		lyid=getlast(lyid); ryid=splay(ryid);
		y[lyid].c[1]=ryid; y[ryid].p=lyid; calc(lyid);
		return lyid;
	}
	int connect(int lyid,int myid,int ryid) {
		return connect(connect(lyid,myid),ryid);
	}
	void disconnect(int lyid,int &ryid) {
		lyid=splay(lyid);
		ryid=y[lyid].c[1];
		if(ryid!=-1) {
			y[lyid].c[1]=y[ryid].p=-1;
			calc(lyid);
		}
	}
	void split(int yid,int &lyid,int &hyid,int val) {
		if(yid==-1) { lyid=hyid=-1; return; }
		yid=splay(yid);
		lyid=-1;
		for(int cyid=yid;cyid!=-1;) {
			if(y[cyid].val<val) {
				lyid=cyid;
				cyid=y[cyid].c[1];
			} else {
				cyid=y[cyid].c[0];
			}
		}
		if(lyid!=-1) disconnect(lyid,hyid); else hyid=yid;
	}

	void split(int yid,int &lyid,int &myid,int &hyid,int val) {
		split(yid,lyid,yid,val);
		split(yid,myid,hyid,val+1);
	}
	int removerange(int &yid,int lval,int hval) {
		int lyid,hyid,ryid=yid;
		split(ryid,lyid,ryid,lval);
		split(ryid,ryid,hyid,hval+1);
		yid=connect(lyid,hyid);
		return ryid;
	}
	int getfirst(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[0]!=-1) yid=y[yid].c[0];
		return splay(yid);
	}
	int getlast(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[1]!=-1) yid=y[yid].c[1];
		return splay(yid);
	}
	void print(int yid) {
		if(yid==-1) { printf("-"); return; }
		printf("["); print(y[yid].c[0]); printf("%d",y[yid].val); print(y[yid].c[1]); printf("]");
	}
} YT;
YT yt;

typedef struct B {
	int ly,hy,yid,ufid;
	int p; int c[2];
} B;

typedef struct BT {
	B b[200000]; int nb;
	int bid;
	BT() { nb=0; bid=-1; }
	int childindex(int x,int y) {
		assert(x!=-1);
		assert(y!=-1);
		if(b[x].c[0]==y) return 0;
		if(b[x].c[1]==y) return 1;
		assert(false);
		return -1;
	}
	void rotate(int x,int xi) {
		int y=b[x].c[xi];
		assert(x!=-1);
		assert(y!=-1);
		b[y].p=b[x].p; if(b[y].p!=-1) { b[b[y].p].c[childindex(b[y].p,x)]=y; }
		b[x].c[xi]=b[y].c[1-xi]; if(b[x].c[xi]!=-1) b[b[x].c[xi]].p=x;
		b[y].c[1-xi]=x; b[x].p=y;
	}
	int splay(int x) {
		assert(x!=-1);
		while(b[x].p!=-1) {
			int y=b[x].p,yi=childindex(y,x);
			if(b[y].p==-1) { rotate(y,yi); continue; }
			int z=b[y].p,zi=childindex(z,y);
			if(yi==zi) { rotate(z,zi); rotate(y,yi); }
			else { rotate(y,yi); rotate(z,zi); }
		}
		return x;
	}
	void disconnect(int lbid,int &rbid) {
		lbid=splay(lbid);
		rbid=b[lbid].c[1];
		if(rbid!=-1) b[lbid].c[1]=b[rbid].p=-1;
	}
	int connect(int lbid,int rbid) {
		if(rbid==-1) return lbid;
		if(lbid==-1) return rbid;
		lbid=getlast(lbid); rbid=splay(rbid);
		b[lbid].c[1]=rbid; b[rbid].p=lbid; return lbid;
	}
	void splitly(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1;
		for(int cbid=bid;cbid!=-1;) {
			if(b[cbid].ly<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}
	void splithy(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1;
		for(int cbid=bid;cbid!=-1;) {
			if(b[cbid].hy<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}

	int removerange(int ly,int hy) {
		int lbid,hbid,rbid=bid;
		splithy(rbid,lbid,rbid,ly); // all b with b.hy < ly
		splitly(rbid,rbid,hbid,hy+1); // all b with b.ly <= hy
		bid=connect(lbid,hbid);
		return rbid;
	}
	void insert(int nbid) {
		//printf("inserting %d\n",nbid);
		//printroot();
		int lbid,hbid;
		splitly(bid,lbid,hbid,b[nbid].ly);
		//printf("%d %d\n",lbid,hbid);
		bid=connect(connect(lbid,nbid),hbid);
		//printf("->\n");
		//printroot();
	}
	int getfirst(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[0]!=-1) bid=b[bid].c[0];
		return splay(bid);
	}
	int getlast(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[1]!=-1) bid=b[bid].c[1];
		return splay(bid);
	}
	void printroot() {
		if(bid==-1) { printf("empty\n"); return; }
		bid=splay(bid);
		print(bid,0);
	}
	void print(int bid,int d) {
		if(bid==-1) return;
		print(b[bid].c[0],d+1);
		REP(i,d) printf("  "); printf("%d: [%d..%d] cnt=%d uf=%d ",bid,b[bid].ly,b[bid].hy,yt.y[yt.splay(b[bid].yid)].cnt,b[bid].ufid); yt.print(b[bid].yid); puts("");
		print(b[bid].c[1],d+1);
	}
} BT;
BT bt;

typedef struct E {
	int type; // 0=shor,1=vrt,2=thor
	int id;
} E;
bool operator<(const E &a,const E &b) {
	int ax=a.type==1?in.x1[a.id]:a.type==0?in.x1[a.id]:in.x2[a.id];
	int bx=b.type==1?in.x1[b.id]:b.type==0?in.x1[b.id]:in.x2[b.id];
	if(ax!=bx) return ax<bx;
	if(a.type!=b.type) return a.type<b.type;
	return in.y1[a.id]<in.y1[b.id];
}

typedef struct ELST {
	E e[400000]; int ne;
	void init() {
		ne=0;
		REP(i,in.n) if(in.x1[i]==in.x2[i]) {
			e[ne].type=1; e[ne].id=i; ++ne;
		} else if(in.y1[i]==in.y2[i]) {
			e[ne].type=0; e[ne].id=i; ++ne;
			e[ne].type=2; e[ne].id=i; ++ne;
		} else {
			assert(false);
		}
		sort(e,e+ne);
	}
	void process() {
		REP(i,in.n) uf.create(i,in.x2[i]-in.x1[i]+in.y2[i]-in.y1[i]);
		REP(ei,ne) {
			int id=e[ei].id;
			//bt.printroot();
			//printf("processing %d (type=%d)\n",id,e[ei].type);
			if(e[ei].type==0) {
				// create a new block
				// insert block into BT (possibly splitting existing block)
				int yid=yt.ny++;
				Y &y=yt.y[yid];
				y.p=-1,y.c[0]=-1,y.c[1]=-1,y.val=in.y1[id],y.cnt=1;
				int bid=bt.nb++;
				B &b=bt.b[bid];
				b.p=-1,b.c[0]=-1,b.c[1]=-1,b.ly=y.val,b.hy=y.val,b.ufid=id,b.yid=yid;
				int obid=bt.removerange(y.val,y.val);
				if(obid==-1) {
					bt.insert(bid);
				} else {
					B &ob=bt.b[obid];
					assert(ob.p==-1&&ob.c[0]==-1&&ob.c[1]==-1);
					int loyid,moyid,hoyid;
					yt.split(ob.yid,loyid,moyid,hoyid,y.val);
					assert(loyid!=-1&&moyid==-1&&hoyid!=-1);
					int nbid=bt.nb++;
					B &nb=bt.b[nbid];
					nb.p=-1,nb.c[0]=-1,nb.c[1]=-1,nb.ly=yt.y[yt.getfirst(hoyid)].val,nb.hy=ob.hy,nb.ufid=ob.ufid,nb.yid=hoyid;
					ob.hy=yt.y[yt.getlast(loyid)].val,ob.yid=loyid;
					bt.insert(obid); bt.insert(bid); bt.insert(nbid);
				}
			} else if(e[ei].type==2) {
				// find block
				// remove from block
				// if block is empty, remove from BT
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				assert(bid!=-1);
				B &b=bt.b[bid];
				assert(b.p==-1&&b.c[0]==-1&&b.c[1]==-1);
				int yid=yt.removerange(b.yid,in.y1[id],in.y2[id]);
				//printf("remove yid(%d,%d,%d) [%d]: ",b.yid,in.y1[id],in.y2[id],b.yid); yt.print(yid); printf("\n");
				assert(yid!=-1);
				Y &y=yt.y[yid];
				assert(y.p==-1&&y.c[0]==-1&&y.c[1]==-1);
				if(b.yid!=-1) {
					b.ly=yt.y[yt.getfirst(b.yid)].val;
					b.hy=yt.y[yt.getlast(b.yid)].val;
					bt.insert(bid);
				}
			} else if(e[ei].type==1) {
				// find blocks and merge them:
				// o merge B
				// o merge YT
				// o remove one from BT
				// o merge in UF
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				//printf("removed:\n"); bt.print(bt.splay(bid),0);
				//printf("remaining:\n"); bt.printroot();
				if(bid==-1) continue;
				uf.unite(id,bt.b[bid].ufid);
				reduceinblock(bid,in.y1[id],in.y2[id]);
				//printf("united\n");
				while(true) {
					bid=bt.getfirst(bid);
					//printf("first=%d\n",bid);
					B &b=bt.b[bid];
					int nbid=b.c[1];
					if(nbid==-1) break;
					reduceinblock(nbid,in.y1[id],in.y2[id]);
					b.c[1]=-1; bt.b[nbid].p=-1; nbid=bt.getfirst(nbid);
					B &nb=bt.b[nbid];
					//printf("merging %d and %d\n",bid,nbid);
					nb.ly=b.ly;
					int yid=yt.splay(b.yid),nyid=yt.getfirst(nb.yid);
					Y &ny=yt.y[nyid];
					Y &y=yt.y[yid];
					ny.c[0]=yid; y.p=nyid; yt.calc(nyid);
					int ufid=b.ufid,nufid=nb.ufid;
					uf.unite(ufid,nufid);
					bid=nbid;
				}
				bt.insert(bid);
			}
		}
	}

	void reduceinblock(int bid,int y1,int y2) {
		B &b=bt.b[bid];
		int lyid,hyid,ryid=b.yid;
		yt.split(ryid,lyid,ryid,y1);
		yt.split(ryid,ryid,hyid,y2+1);
		assert(ryid!=-1);
		int cnt=yt.y[yt.splay(ryid)].cnt;
		//printf("cnt=%d\n",cnt);
		uf.reduce(b.ufid,cnt-1);
		b.yid=yt.connect(lyid,ryid,hyid);
	}
} ELST;
ELST elst;

void run() {
	in.read();
	elst.init();
	elst.process();
	int ret=0;
	REP(i,in.n) if(uf.find(i)==i) {
		int cur=uf.len[i];
		if(cur>ret) ret=cur;
	}
	printf("%d\n",ret);
}

int main() {
	run();
	return 0;
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

int pcnt[100];

typedef struct IN {
	int n;
	int x1[200000],y1[200000],x2[200000],y2[200000];
	void read() {
		scanf("%d",&n);
		REP(i,n) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
	}
	void gen() {
		int each=100000; n=2*each;
		REP(i,each) x1[i]=x2[i]=i,y1[i]=rand()%each,y2[i]=y1[i]+1+rand()%each;
		REP(i,each) x1[each+i]=rand()%each,x2[each+i]=x1[each+i]+1+rand()%each,y1[each+i]=y2[each+i]=i;
	}
	void print() {
		printf("%d\n",n);
		REP(i,n) printf("%d %d %d %d\n",x1[i],y1[i],x2[i],y2[i]);
	}
} IN;
IN in;

typedef struct UF {
	int par[200000];
	int rnk[200000];
	ll len[200000];

	int q[200000],nq;

	void create(int a,int nlen) {
		par[a]=a; rnk[a]=0; len[a]=nlen;
	}
	int find(int a) {
		//if(debug) printf("find(%d): %d/%lld\n",a,par[a],len[a]);
		nq=0;
		while(par[a]!=a) {
			q[nq++]=a;
			a=par[a];
		}
		REP(i,nq) par[q[i]]=a;
		return a;
	}
	void unite(int a,int b) {
		++pcnt[1];
		a=find(a); b=find(b);
		if(a==b) {
			//printf("decreasing\n");
			--len[a]; return;
		}
		if(rnk[a]<rnk[b]) swap(a,b);
		par[b]=a; len[a]+=len[b];
	}
	void reduce(int a,int by) {
		if(by==0) return;
		//printf("reducing by %d\n",by);
		++pcnt[2];
		a=find(a); len[a]-=by;
	}
} UF;
UF uf;

typedef struct Y {
	int val,cnt;
	int p; int c[2];
} Y;

typedef struct YT {
	Y y[200000]; int ny;
	void init() { ny=0; }
	void calc(int a) {
		y[a].cnt=1+(y[a].c[0]!=-1?y[y[a].c[0]].cnt:0)+(y[a].c[1]!=-1?y[y[a].c[1]].cnt:0);
	}
	int childindex(int a,int b) {
		assert(a!=-1);
		assert(b!=-1);
		if(y[a].c[0]==b) return 0;
		if(y[a].c[1]==b) return 1;
		assert(false);
		return -1;
	}
	void rotate(int a,int ai) {
		++pcnt[3];
		int b=y[a].c[ai];
		assert(a!=-1);
		assert(b!=-1);
		y[b].p=y[a].p; if(y[b].p!=-1) { y[y[b].p].c[childindex(y[b].p,a)]=b; }
		y[a].c[ai]=y[b].c[1-ai]; if(y[a].c[ai]!=-1) y[y[a].c[ai]].p=a;
		y[b].c[1-ai]=a; y[a].p=b;
		calc(a); calc(b);
	}
	int splay(int a) {
		++pcnt[4];
		assert(a!=-1);
		while(y[a].p!=-1) {
			++pcnt[5];
			int b=y[a].p,bi=childindex(b,a);
			if(y[b].p==-1) { rotate(b,bi); continue; }
			int c=y[b].p,ci=childindex(c,b);
			if(bi==ci) { rotate(c,ci); rotate(b,bi); }
			else { rotate(b,bi); rotate(c,ci); }
		}
		return a;
	}
	int connect(int lyid,int ryid) {
		if(ryid==-1) return lyid;
		if(lyid==-1) return ryid;
		lyid=getlast(lyid); ryid=splay(ryid);
		y[lyid].c[1]=ryid; y[ryid].p=lyid; calc(lyid);
		return lyid;
	}
	int connect(int lyid,int myid,int ryid) {
		return connect(connect(lyid,myid),ryid);
	}
	void disconnect(int lyid,int &ryid) {
		lyid=splay(lyid);
		ryid=y[lyid].c[1];
		if(ryid!=-1) {
			y[lyid].c[1]=y[ryid].p=-1;
			calc(lyid);
		}
	}
	void split(int yid,int &lyid,int &hyid,int val) {
		if(yid==-1) { lyid=hyid=-1; return; }
		yid=splay(yid);
		lyid=-1; int pyid=yid;
		for(int cyid=yid;cyid!=-1;) {
			++pcnt[15]; pyid=cyid;
			if(y[cyid].val<val) {
				lyid=cyid;
				cyid=y[cyid].c[1];
			} else {
				cyid=y[cyid].c[0];
			}
		}
		if(pyid!=-1) yid=splay(pyid);
		if(lyid!=-1) disconnect(lyid,hyid); else hyid=yid;
	}

	void split(int yid,int &lyid,int &myid,int &hyid,int val) {
		split(yid,lyid,yid,val);
		split(yid,myid,hyid,val+1);
	}
	int removerange(int &yid,int lval,int hval) {
		int lyid,hyid,ryid=yid;
		split(ryid,lyid,ryid,lval);
		split(ryid,ryid,hyid,hval+1);
		yid=connect(lyid,hyid);
		return ryid;
	}
	int getfirst(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[0]!=-1) {
			++pcnt[6];
			yid=y[yid].c[0];
		}
		return splay(yid);
	}
	int getlast(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[1]!=-1) {
			++pcnt[7];
			yid=y[yid].c[1];
		}
		return splay(yid);
	}
	bool check(int yid,int &py) {
		if(y[yid].c[0]!=-1&&!check(y[yid].c[0],py)) return false;
		if(y[yid].val<=py) { printf("yerror: not strictly increasing at %d (prev=%d mine=%d)\n",yid,py,y[yid].val); return false; }
		if(y[yid].c[1]!=-1&&!check(y[yid].c[1],py)) return false;
		return true;
	}
	void print(int yid) {
		if(yid==-1) { printf("-"); return; }
		printf("["); print(y[yid].c[0]); printf("%d",y[yid].val); print(y[yid].c[1]); printf("]");
	}
} YT;
YT yt;

typedef struct B {
	int ly,hy,yid,ufid;
	int p; int c[2];
} B;

typedef struct BT {
	B b[200000]; int nb;
	int bid;
	void init() { nb=0; bid=-1; }
	int childindex(int x,int y) {
		assert(x!=-1);
		assert(y!=-1);
		if(b[x].c[0]==y) return 0;
		if(b[x].c[1]==y) return 1;
		assert(false);
		return -1;
	}
	void rotate(int x,int xi) {
			++pcnt[8];
		int y=b[x].c[xi];
		assert(x!=-1);
		assert(y!=-1);
		b[y].p=b[x].p; if(b[y].p!=-1) { b[b[y].p].c[childindex(b[y].p,x)]=y; }
		b[x].c[xi]=b[y].c[1-xi]; if(b[x].c[xi]!=-1) b[b[x].c[xi]].p=x;
		b[y].c[1-xi]=x; b[x].p=y;
	}
	int splay(int x) {
			++pcnt[9];
		assert(x!=-1);
		while(b[x].p!=-1) {
			++pcnt[10];
			int y=b[x].p,yi=childindex(y,x);
			if(b[y].p==-1) { rotate(y,yi); continue; }
			int z=b[y].p,zi=childindex(z,y);
			if(yi==zi) { rotate(z,zi); rotate(y,yi); }
			else { rotate(y,yi); rotate(z,zi); }
		}
		return x;
	}
	void disconnect(int lbid,int &rbid) {
		lbid=splay(lbid);
		rbid=b[lbid].c[1];
		if(rbid!=-1) b[lbid].c[1]=b[rbid].p=-1;
	}
	int connect(int lbid,int rbid) {
		if(rbid==-1) return lbid;
		if(lbid==-1) return rbid;
		lbid=getlast(lbid); rbid=splay(rbid);
		b[lbid].c[1]=rbid; b[rbid].p=lbid; return lbid;
	}
	void splitly(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[16]; pbid=cbid;
			if(b[cbid].ly<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}
	void splithy(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[17]; pbid=cbid;
			if(b[cbid].hy<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}

	int removerange(int ly,int hy) {
		int lbid,hbid,rbid=bid;
		splithy(rbid,lbid,rbid,ly); // all b with b.hy < ly
		splitly(rbid,rbid,hbid,hy+1); // all b with b.ly <= hy
		bid=connect(lbid,hbid);
		return rbid;
	}
	void insert(int nbid) {
		//printf("inserting %d\n",nbid);
		//printroot();
		int lbid,hbid;
		splitly(bid,lbid,hbid,b[nbid].ly);
		//printf("%d %d\n",lbid,hbid);
		bid=connect(connect(lbid,nbid),hbid);
		//printf("->\n");
		//printroot();
	}
	int getfirst(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[0]!=-1) {
			++pcnt[11];
			bid=b[bid].c[0];
		}
		return splay(bid);
	}
	int getlast(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[1]!=-1) {
			++pcnt[12];
			bid=b[bid].c[1];
		}
		return splay(bid);
	}
	bool checkroot() {
		if(bid==-1) return true;
		bid=splay(bid);
		int py=INT_MIN; return check(bid,py);
	}
	bool check(int bid,int &py) {
		if(b[bid].c[0]!=-1&&!check(b[bid].c[0],py)) return false;
		if(b[bid].ly<=py) { printf("error: ranges overlap. bid=%d, ly=%d, py=%d\n",bid,b[bid].ly,py); return false; }
		py=b[bid].hy;
		int npy=INT_MIN; if(!yt.check(yt.splay(b[bid].yid),npy)) return false;
		int ly=yt.y[yt.getfirst(b[bid].yid)].val,hy=yt.y[yt.getlast(b[bid].yid)].val;
		if(b[bid].ly!=ly) { printf("error: minimum not same at bid=%d (have %d want %d)\n",bid,b[bid].ly,ly); return false; }
		if(b[bid].hy!=hy) { printf("error: maximum not same at bid=%d (have %d want %d)\n",bid,b[bid].hy,hy); return false; }
		if(b[bid].c[1]!=-1&&!check(b[bid].c[1],py)) return false;
		return true;
	}
	void printroot() {
		if(bid==-1) { printf("empty\n"); return; }
		bid=splay(bid);
		print(bid,0);
	}
	void print(int bid,int d) {
		if(bid==-1) return;
		print(b[bid].c[0],d+1);
		REP(i,d) printf("  "); printf("%d: [%d..%d] cnt=%d uf=%d ",bid,b[bid].ly,b[bid].hy,yt.y[yt.splay(b[bid].yid)].cnt,b[bid].ufid); yt.print(b[bid].yid); puts("");
		print(b[bid].c[1],d+1);
	}
} BT;
BT bt;

typedef struct E {
	int type; // 0=shor,1=vrt,2=thor
	int id;
} E;
bool operator<(const E &a,const E &b) {
	int ax=a.type==1?in.x1[a.id]:a.type==0?in.x1[a.id]:in.x2[a.id];
	int bx=b.type==1?in.x1[b.id]:b.type==0?in.x1[b.id]:in.x2[b.id];
	if(ax!=bx) return ax<bx;
	if(a.type!=b.type) return a.type<b.type;
	return in.y1[a.id]<in.y1[b.id];
}

typedef struct ELST {
	E e[400000]; int ne;
	void init() {
		ne=0;
		REP(i,in.n) if(in.x1[i]==in.x2[i]) {
			e[ne].type=1; e[ne].id=i; ++ne;
		} else if(in.y1[i]==in.y2[i]) {
			e[ne].type=0; e[ne].id=i; ++ne;
			e[ne].type=2; e[ne].id=i; ++ne;
		} else {
			assert(false);
		}
		sort(e,e+ne);
	}
	void process() {
		REP(i,in.n) uf.create(i,in.x2[i]-in.x1[i]+in.y2[i]-in.y1[i]);
		REP(ei,ne) {
			++pcnt[13];
			int id=e[ei].id;
			//if(!bt.checkroot()) { bt.printroot(); exit(0); }
			//bt.printroot();
			//printf("processing %d (type=%d)\n",id,e[ei].type);
			if(e[ei].type==0) {
				// create a new block
				// insert block into BT (possibly splitting existing block)
				int yid=yt.ny++;
				Y &y=yt.y[yid];
				y.p=-1,y.c[0]=-1,y.c[1]=-1,y.val=in.y1[id],y.cnt=1;
				int bid=bt.nb++;
				B &b=bt.b[bid];
				b.p=-1,b.c[0]=-1,b.c[1]=-1,b.ly=y.val,b.hy=y.val,b.ufid=id,b.yid=yid;
				int obid=bt.removerange(y.val,y.val);
				if(obid==-1) {
					bt.insert(bid);
				} else {
					B &ob=bt.b[obid];
					assert(ob.p==-1&&ob.c[0]==-1&&ob.c[1]==-1);
					int loyid,moyid,hoyid;
					yt.split(ob.yid,loyid,moyid,hoyid,y.val);
					assert(loyid!=-1&&moyid==-1&&hoyid!=-1);
					int nbid=bt.nb++;
					B &nb=bt.b[nbid];
					nb.p=-1,nb.c[0]=-1,nb.c[1]=-1,nb.ly=yt.y[yt.getfirst(hoyid)].val,nb.hy=ob.hy,nb.ufid=ob.ufid,nb.yid=hoyid;
					ob.hy=yt.y[yt.getlast(loyid)].val,ob.yid=loyid;
					bt.insert(obid); bt.insert(bid); bt.insert(nbid);
				}
			} else if(e[ei].type==2) {
				// find block
				// remove from block
				// if block is empty, remove from BT
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				assert(bid!=-1);
				B &b=bt.b[bid];
				assert(b.p==-1&&b.c[0]==-1&&b.c[1]==-1);
				int yid=yt.removerange(b.yid,in.y1[id],in.y2[id]);
				//printf("remove yid(%d,%d,%d) [%d]: ",b.yid,in.y1[id],in.y2[id],b.yid); yt.print(yid); printf("\n");
				assert(yid!=-1);
				Y &y=yt.y[yid];
				assert(y.p==-1&&y.c[0]==-1&&y.c[1]==-1);
				if(b.yid!=-1) {
					b.ly=yt.y[yt.getfirst(b.yid)].val;
					b.hy=yt.y[yt.getlast(b.yid)].val;
					bt.insert(bid);
				}
			} else if(e[ei].type==1) {
				// find blocks and merge them:
				// o merge B
				// o merge YT
				// o remove one from BT
				// o merge in UF
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				//printf("removed:\n"); bt.print(bt.splay(bid),0);
				//printf("remaining:\n"); bt.printroot();
				if(bid==-1) continue;
				bid=bt.getfirst(bid);
				if(reduceinblock(bid,in.y1[id],in.y2[id]))
					uf.unite(id,bt.b[bid].ufid);
				//printf("united\n");
				while(true) {
					++pcnt[14];
					//printf("first=%d\n",bid);
					B &b=bt.b[bid];
					int nbid=b.c[1];
					if(nbid==-1) break;
					while(bt.b[nbid].c[0]!=-1) nbid=bt.b[nbid].c[0];
					nbid=bt.splay(nbid);
					assert(bt.b[nbid].c[0]==bid&&bt.b[bid].c[0]==-1&&bt.b[bid].c[1]==-1);
					reduceinblock(nbid,in.y1[id],in.y2[id]);
					B &nb=bt.b[nbid];
					nb.c[0]=b.p=-1;
					//printf("merging %d and %d\n",bid,nbid);
					nb.ly=b.ly;
					int yid=yt.splay(b.yid),nyid=yt.getfirst(nb.yid);
					Y &ny=yt.y[nyid];
					Y &y=yt.y[yid];
					ny.c[0]=yid; y.p=nyid; yt.calc(nyid);
					int ufid=b.ufid,nufid=nb.ufid;
					uf.unite(ufid,nufid);
					bid=nbid;
				}
				bt.insert(bid);
			}
		}
	}

	bool reduceinblock(int bid,int y1,int y2) {
		B &b=bt.b[bid];
		int lyid,hyid,ryid=b.yid;
		yt.split(ryid,lyid,ryid,y1);
		yt.split(ryid,ryid,hyid,y2+1);
		/*printf("bid=%d\n",bid);
		printf("l: "); if(lyid==-1) printf("-"); else yt.print(yt.splay(lyid)); puts("");
		printf("m: "); if(ryid==-1) printf("-"); else yt.print(yt.splay(ryid)); puts("");
		printf("h: "); if(hyid==-1) printf("-"); else yt.print(yt.splay(hyid)); puts(""); */
		if(ryid!=-1) {
			int cnt=yt.y[yt.splay(ryid)].cnt;
			uf.reduce(b.ufid,cnt-1);
		}
		b.yid=yt.connect(lyid,ryid,hyid);
		return ryid!=-1;
	}
} ELST;
ELST elst;

void run() {
	yt.init(); bt.init(); elst.init();
	elst.process();
	ll ret=0;
	REP(i,in.n) {
		if(uf.find(i)==i) {
			ll cur=uf.len[i];
			if(cur>ret) ret=cur;
		}
	}
	cout<<ret<<endl;
/*	REP(i,18) fprintf(stderr,"p%d: %d\n",i,pcnt[i]);
	fprintf(stderr,"n: %d\n",in.n);
	fprintf(stderr,"ny: %d\n",yt.ny);
	fprintf(stderr,"nb: %d\n",bt.nb);
	fprintf(stderr,"ne: %d\n",elst.ne); */
}

int main() {
	in.read(); run(); return 0;
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <list>
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

int pcnt[100];

typedef struct IN {
	int n;
	int x1[200000],y1[200000],x2[200000],y2[200000];
	void read() {
		scanf("%d",&n);
		REP(i,n) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]);
	}
	void gen() {
		int each=100000; n=2*each;
		REP(i,each) x1[i]=x2[i]=i,y1[i]=0,y2[i]=each-1;
		REP(i,each) x1[each+i]=0,x2[each+i]=each-1,y1[each+i]=y2[each+i]=i;
	}
} IN;
IN in;
bool debug=false;
typedef struct UF {
	int par[200000];
	int rnk[200000];
	ll len[200000];

	int q[200000],nq;

	void create(int a,int nlen) {
		par[a]=a; rnk[a]=0; len[a]=nlen;
	}
	int find(int a) {
		//if(debug) printf("find(%d): %d/%lld\n",a,par[a],len[a]);
		nq=0;
		while(par[a]!=a) {
			q[nq++]=a;
			a=par[a];
		}
		REP(i,nq) par[q[i]]=a;
		return a;
	}
	void unite(int a,int b) {
		++pcnt[1];
		a=find(a); b=find(b);
		if(a==b) { --len[a]; return; }
		if(rnk[a]<rnk[b]) swap(a,b);
		par[b]=a; len[a]+=len[b];
	}
	void reduce(int a,int by) {
		++pcnt[2];
		a=find(a); len[a]-=by;
	}
} UF;
UF uf;

typedef struct Y {
	int val,cnt;
	int p; int c[2];
} Y;

typedef struct YT {
	Y y[200000]; int ny;
	YT() { ny=0; }
	void calc(int a) {
		y[a].cnt=1+(y[a].c[0]!=-1?y[y[a].c[0]].cnt:0)+(y[a].c[1]!=-1?y[y[a].c[1]].cnt:0);
	}
	int childindex(int a,int b) {
		assert(a!=-1);
		assert(b!=-1);
		if(y[a].c[0]==b) return 0;
		if(y[a].c[1]==b) return 1;
		assert(false);
		return -1;
	}
	void rotate(int a,int ai) {
		++pcnt[3];
		int b=y[a].c[ai];
		assert(a!=-1);
		assert(b!=-1);
		y[b].p=y[a].p; if(y[b].p!=-1) { y[y[b].p].c[childindex(y[b].p,a)]=b; }
		y[a].c[ai]=y[b].c[1-ai]; if(y[a].c[ai]!=-1) y[y[a].c[ai]].p=a;
		y[b].c[1-ai]=a; y[a].p=b;
		calc(a); calc(b);
	}
	int splay(int a) {
		++pcnt[4];
		assert(a!=-1);
		while(y[a].p!=-1) {
			++pcnt[5];
			int b=y[a].p,bi=childindex(b,a);
			if(y[b].p==-1) { rotate(b,bi); continue; }
			int c=y[b].p,ci=childindex(c,b);
			if(bi==ci) { rotate(c,ci); rotate(b,bi); }
			else { rotate(b,bi); rotate(c,ci); }
		}
		return a;
	}
	int connect(int lyid,int ryid) {
		if(ryid==-1) return lyid;
		if(lyid==-1) return ryid;
		lyid=getlast(lyid); ryid=splay(ryid);
		y[lyid].c[1]=ryid; y[ryid].p=lyid; calc(lyid);
		return lyid;
	}
	int connect(int lyid,int myid,int ryid) {
		return connect(connect(lyid,myid),ryid);
	}
	void disconnect(int lyid,int &ryid) {
		lyid=splay(lyid);
		ryid=y[lyid].c[1];
		if(ryid!=-1) {
			y[lyid].c[1]=y[ryid].p=-1;
			calc(lyid);
		}
	}
	void split(int yid,int &lyid,int &hyid,int val) {
		if(yid==-1) { lyid=hyid=-1; return; }
		yid=splay(yid);
		lyid=-1; int pyid=yid;
		for(int cyid=yid;cyid!=-1;) {
			++pcnt[15]; pyid=cyid;
			if(y[cyid].val<val) {
				lyid=cyid;
				cyid=y[cyid].c[1];
			} else {
				cyid=y[cyid].c[0];
			}
		}
		if(pyid!=-1) yid=splay(pyid);
		if(lyid!=-1) disconnect(lyid,hyid); else hyid=yid;
	}

	void split(int yid,int &lyid,int &myid,int &hyid,int val) {
		split(yid,lyid,yid,val);
		split(yid,myid,hyid,val+1);
	}
	int removerange(int &yid,int lval,int hval) {
		int lyid,hyid,ryid=yid;
		split(ryid,lyid,ryid,lval);
		split(ryid,ryid,hyid,hval+1);
		yid=connect(lyid,hyid);
		return ryid;
	}
	int getfirst(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[0]!=-1) {
			++pcnt[6];
			yid=y[yid].c[0];
		}
		return splay(yid);
	}
	int getlast(int yid) {
		assert(yid!=-1);
		yid=splay(yid);
		while(y[yid].c[1]!=-1) {
			++pcnt[7];
			yid=y[yid].c[1];
		}
		return splay(yid);
	}
	void print(int yid) {
		if(yid==-1) { printf("-"); return; }
		printf("["); print(y[yid].c[0]); printf("%d",y[yid].val); print(y[yid].c[1]); printf("]");
	}
} YT;
YT yt;

typedef struct B {
	int ly,hy,yid,ufid;
	int p; int c[2];
} B;

typedef struct BT {
	B b[200000]; int nb;
	int bid;
	BT() { nb=0; bid=-1; }
	int childindex(int x,int y) {
		assert(x!=-1);
		assert(y!=-1);
		if(b[x].c[0]==y) return 0;
		if(b[x].c[1]==y) return 1;
		assert(false);
		return -1;
	}
	void rotate(int x,int xi) {
			++pcnt[8];
		int y=b[x].c[xi];
		assert(x!=-1);
		assert(y!=-1);
		b[y].p=b[x].p; if(b[y].p!=-1) { b[b[y].p].c[childindex(b[y].p,x)]=y; }
		b[x].c[xi]=b[y].c[1-xi]; if(b[x].c[xi]!=-1) b[b[x].c[xi]].p=x;
		b[y].c[1-xi]=x; b[x].p=y;
	}
	int splay(int x) {
			++pcnt[9];
		assert(x!=-1);
		while(b[x].p!=-1) {
			++pcnt[10];
			int y=b[x].p,yi=childindex(y,x);
			if(b[y].p==-1) { rotate(y,yi); continue; }
			int z=b[y].p,zi=childindex(z,y);
			if(yi==zi) { rotate(z,zi); rotate(y,yi); }
			else { rotate(y,yi); rotate(z,zi); }
		}
		return x;
	}
	void disconnect(int lbid,int &rbid) {
		lbid=splay(lbid);
		rbid=b[lbid].c[1];
		if(rbid!=-1) b[lbid].c[1]=b[rbid].p=-1;
	}
	int connect(int lbid,int rbid) {
		if(rbid==-1) return lbid;
		if(lbid==-1) return rbid;
		lbid=getlast(lbid); rbid=splay(rbid);
		b[lbid].c[1]=rbid; b[rbid].p=lbid; return lbid;
	}
	void splitly(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[16]; pbid=cbid;
			if(b[cbid].ly<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}
	void splithy(int bid,int &lbid,int &hbid,int val) {
		if(bid==-1) { lbid=hbid=-1; return; }
		bid=splay(bid);
		lbid=-1; int pbid=bid;
		for(int cbid=bid;cbid!=-1;) {
			++pcnt[17]; pbid=cbid;
			if(b[cbid].hy<val) {
				lbid=cbid;
				cbid=b[cbid].c[1];
			} else {
				cbid=b[cbid].c[0];
			}
		}
		if(pbid!=-1) bid=splay(pbid);
		if(lbid!=-1) disconnect(lbid,hbid); else hbid=bid;
	}

	int removerange(int ly,int hy) {
		int lbid,hbid,rbid=bid;
		splithy(rbid,lbid,rbid,ly); // all b with b.hy < ly
		splitly(rbid,rbid,hbid,hy+1); // all b with b.ly <= hy
		bid=connect(lbid,hbid);
		return rbid;
	}
	void insert(int nbid) {
		//printf("inserting %d\n",nbid);
		//printroot();
		int lbid,hbid;
		splitly(bid,lbid,hbid,b[nbid].ly);
		//printf("%d %d\n",lbid,hbid);
		bid=connect(connect(lbid,nbid),hbid);
		//printf("->\n");
		//printroot();
	}
	int getfirst(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[0]!=-1) {
			++pcnt[11];
			bid=b[bid].c[0];
		}
		return splay(bid);
	}
	int getlast(int bid) {
		assert(bid!=-1);
		bid=splay(bid);
		while(b[bid].c[1]!=-1) {
			++pcnt[12];
			bid=b[bid].c[1];
		}
		return splay(bid);
	}
	void printroot() {
		if(bid==-1) { printf("empty\n"); return; }
		bid=splay(bid);
		print(bid,0);
	}
	void print(int bid,int d) {
		if(bid==-1) return;
		print(b[bid].c[0],d+1);
		REP(i,d) printf("  "); printf("%d: [%d..%d] cnt=%d uf=%d ",bid,b[bid].ly,b[bid].hy,yt.y[yt.splay(b[bid].yid)].cnt,b[bid].ufid); yt.print(b[bid].yid); puts("");
		print(b[bid].c[1],d+1);
	}
} BT;
BT bt;

typedef struct E {
	int type; // 0=shor,1=vrt,2=thor
	int id;
} E;
bool operator<(const E &a,const E &b) {
	int ax=a.type==1?in.x1[a.id]:a.type==0?in.x1[a.id]:in.x2[a.id];
	int bx=b.type==1?in.x1[b.id]:b.type==0?in.x1[b.id]:in.x2[b.id];
	if(ax!=bx) return ax<bx;
	if(a.type!=b.type) return a.type<b.type;
	return in.y1[a.id]<in.y1[b.id];
}

typedef struct ELST {
	E e[400000]; int ne;
	void init() {
		ne=0;
		REP(i,in.n) if(in.x1[i]==in.x2[i]) {
			e[ne].type=1; e[ne].id=i; ++ne;
		} else if(in.y1[i]==in.y2[i]) {
			e[ne].type=0; e[ne].id=i; ++ne;
			e[ne].type=2; e[ne].id=i; ++ne;
		} else {
			assert(false);
		}
		sort(e,e+ne);
	}
	void process() {
		REP(i,in.n) uf.create(i,in.x2[i]-in.x1[i]+in.y2[i]-in.y1[i]);
		REP(ei,ne) {
			++pcnt[13];
			int id=e[ei].id;
			//bt.printroot();
			//printf("processing %d (type=%d)\n",id,e[ei].type);
			if(e[ei].type==0) {
				// create a new block
				// insert block into BT (possibly splitting existing block)
				int yid=yt.ny++;
				Y &y=yt.y[yid];
				y.p=-1,y.c[0]=-1,y.c[1]=-1,y.val=in.y1[id],y.cnt=1;
				int bid=bt.nb++;
				B &b=bt.b[bid];
				b.p=-1,b.c[0]=-1,b.c[1]=-1,b.ly=y.val,b.hy=y.val,b.ufid=id,b.yid=yid;
				int obid=bt.removerange(y.val,y.val);
				if(obid==-1) {
					bt.insert(bid);
				} else {
					B &ob=bt.b[obid];
					assert(ob.p==-1&&ob.c[0]==-1&&ob.c[1]==-1);
					int loyid,moyid,hoyid;
					yt.split(ob.yid,loyid,moyid,hoyid,y.val);
					assert(loyid!=-1&&moyid==-1&&hoyid!=-1);
					int nbid=bt.nb++;
					B &nb=bt.b[nbid];
					nb.p=-1,nb.c[0]=-1,nb.c[1]=-1,nb.ly=yt.y[yt.getfirst(hoyid)].val,nb.hy=ob.hy,nb.ufid=ob.ufid,nb.yid=hoyid;
					ob.hy=yt.y[yt.getlast(loyid)].val,ob.yid=loyid;
					bt.insert(obid); bt.insert(bid); bt.insert(nbid);
				}
			} else if(e[ei].type==2) {
				// find block
				// remove from block
				// if block is empty, remove from BT
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				assert(bid!=-1);
				B &b=bt.b[bid];
				assert(b.p==-1&&b.c[0]==-1&&b.c[1]==-1);
				int yid=yt.removerange(b.yid,in.y1[id],in.y2[id]);
				//printf("remove yid(%d,%d,%d) [%d]: ",b.yid,in.y1[id],in.y2[id],b.yid); yt.print(yid); printf("\n");
				assert(yid!=-1);
				Y &y=yt.y[yid];
				assert(y.p==-1&&y.c[0]==-1&&y.c[1]==-1);
				if(b.yid!=-1) {
					b.ly=yt.y[yt.getfirst(b.yid)].val;
					b.hy=yt.y[yt.getlast(b.yid)].val;
					bt.insert(bid);
				}
			} else if(e[ei].type==1) {
				// find blocks and merge them:
				// o merge B
				// o merge YT
				// o remove one from BT
				// o merge in UF
				int bid=bt.removerange(in.y1[id],in.y2[id]);
				//printf("removed:\n"); bt.print(bt.splay(bid),0);
				//printf("remaining:\n"); bt.printroot();
				if(bid==-1) continue;
				uf.unite(id,bt.b[bid].ufid);
				reduceinblock(bid,in.y1[id],in.y2[id]);
				//printf("united\n");
				while(true) {
			++pcnt[14];
					bid=bt.getfirst(bid);
					//printf("first=%d\n",bid);
					B &b=bt.b[bid];
					int nbid=b.c[1];
					if(nbid==-1) break;
					reduceinblock(nbid,in.y1[id],in.y2[id]);
					b.c[1]=-1; bt.b[nbid].p=-1; nbid=bt.getfirst(nbid);
					B &nb=bt.b[nbid];
					//printf("merging %d and %d\n",bid,nbid);
					nb.ly=b.ly;
					int yid=yt.splay(b.yid),nyid=yt.getfirst(nb.yid);
					Y &ny=yt.y[nyid];
					Y &y=yt.y[yid];
					ny.c[0]=yid; y.p=nyid; yt.calc(nyid);
					int ufid=b.ufid,nufid=nb.ufid;
					uf.unite(ufid,nufid);
					bid=nbid;
				}
				bt.insert(bid);
			}
		}
	}

	void reduceinblock(int bid,int y1,int y2) {
		B &b=bt.b[bid];
		int lyid,hyid,ryid=b.yid;
		yt.split(ryid,lyid,ryid,y1);
		yt.split(ryid,ryid,hyid,y2+1);
		assert(ryid!=-1);
		int cnt=yt.y[yt.splay(ryid)].cnt;
		//printf("cnt=%d\n",cnt);
		uf.reduce(b.ufid,cnt-1);
		b.yid=yt.connect(lyid,ryid,hyid);
	}
} ELST;
ELST elst;

void run() {
	in.read();
	//in.gen();
	elst.init();
	elst.process();
	ll ret=0;
	debug=true;
	REP(i,in.n) {
		if(uf.find(i)==i) {
			ll cur=uf.len[i];
			if(cur>ret) ret=cur;
		}
	}
	cout<<ret<<endl;
	REP(i,18) fprintf(stderr,"p%d: %d\n",i,pcnt[i]);
	fprintf(stderr,"n: %d\n",in.n);
	fprintf(stderr,"ny: %d\n",yt.ny);
	fprintf(stderr,"nb: %d\n",bt.nb);
	fprintf(stderr,"ne: %d\n",elst.ne);
}

int main() {
	run();
	return 0;
}


// 10 monthes remaining for red =D
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<cassert>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int BUF = 400005;
const int INF = 1<<30;

enum TYPE {
    HORIZONTAL_BAR_BEGIN = 0,
    VERTICAL_BAR = 1,
    HORIZONTAL_BAR_END = 2
};

class Event {
public:
    int x, y1, y2, type, barId;

    Event(){}
    Event(int x, int y1, int y2, int type, int barId):
        x(x), y1(y1), y2(y2), type(type), barId(barId){}

    bool operator< (const Event &e) const {
        if (x != e.x) return x < e.x;
        return type < e.type;
    }
};

class Range {
public:
    int bottom, top, id;
    Range(){}
    Range(int b, int t, int i):
        bottom(b), top(t), id(i){}
    bool operator< (const Range &r) const {
        if (bottom != r.bottom) return bottom < r.bottom;
        if (top != r.top) return top < r.top;
        return id < r.id;
    }
};

class Group{
public:
  int g[BUF];
  long long sum[BUF];

  Group(){}

  void build(int n){
    for(int i=0;i<n;i++){
      g[i] = i;
      sum[i] = 0;
    }
  }

  int findGroup(int n){
    return (n==g[n] ? n : g[n]=findGroup(g[n]));
  }

  long long findSum(int n){
    return sum[findGroup(n)];
  }

  void mergeGroup(int a, int b){
    g[findGroup(a)] = findGroup(b);
  }

  void mergeSum(int a, int b) {
    // ??: mergeGroup ??????????
    long long A = sum[findGroup(a)];
    long long B = sum[findGroup(b)];
    sum[findGroup(a)] += B;
    sum[findGroup(b)] += A;
  }

  void addSum(int a, int delta) {
    sum[findGroup(a)] += delta;
  }
};

class SegTree{
public:
  int v[BUF*4];
  int idxMax[BUF*4];  // ??????v[i] > 0 ??????? i
  int idxMin[BUF*4];  // ??????v[i] > 0 ??????? i

  SegTree(){
    memset(v,0,sizeof(v));
    memset(idxMax,-1,sizeof(idxMax));
    memset(idxMin,-1,sizeof(idxMin));
  }

  int getMax(int node, int L, int R, int LQ, int RQ){
    if(R<LQ || RQ<L) return -1;
    if(LQ<=L && R<=RQ) return idxMax[node];
    int s = getMax(node*2+1,L,(L+R)/2,LQ,RQ);
    int t = getMax(node*2+2,(L+R)/2+1,R,LQ,RQ);
    return max(s, t);
  }

  int getMin(int node, int L, int R, int LQ, int RQ){
    if(R<LQ || RQ<L) return -1;
    if(LQ<=L && R<=RQ) return idxMin[node];
    int s = getMin(node*2+1,L,(L+R)/2,LQ,RQ);
    int t = getMin(node*2+2,(L+R)/2+1,R,LQ,RQ);
    if (s == -1) return t;
    if (t == -1) return s;
    return min(s, t);
  }

  int getSum(int node, int L, int R, int LQ, int RQ){
    if(R<LQ || RQ<L) return 0;
    if(LQ<=L && R<=RQ) return v[node];
    int s = getSum(node*2+1,L,(L+R)/2,LQ,RQ);
    int t = getSum(node*2+2,(L+R)/2+1,R,LQ,RQ);
    return s + t;
  }

  void update(int node, int L, int R, int Q, int delta){
    if(R<Q || Q<L) return;
    if(L==R) {
        v[node] += delta;
        idxMax[node] = idxMin[node] = (v[node] > 0 ? L : -1);
        return;
    }
    update(node*2+1,L,(L+R)/2,Q,delta);
    update(node*2+2,(L+R)/2+1,R,Q,delta);

    v[node] = v[node*2+1] + v[node*2+2];
    idxMax[node] = max(idxMax[node*2+1], idxMax[node*2+2]);
    if (idxMin[node*2+1] == -1)
        idxMin[node] = idxMin[node*2+2];
    else if (idxMin[node*2+2] == -1)
        idxMin[node] = idxMin[node*2+1];
    else
        idxMin[node] = min(idxMin[node*2+1], idxMin[node*2+2]);
  }
};

class Bar {
public:
    int x1, y1, x2, y2;
    Bar(){}
    Bar(int x1, int y1, int x2, int y2):
        x1(x1), y1(y1), x2(x2), y2(y2){}
};

int nBar;
Bar bar[BUF];

void read() {
    scanf("%d", &nBar);
    for (int i = 0; i < nBar; ++i) {
        Bar &b = bar[i];
        scanf("%d%d%d%d", &b.x1, &b.y1, &b.x2, &b.y2);
    }
}

void work() {
    map<int, int> y2val;
    map<int, int> val2y;
    set<int> ySet;
    for (int i = 0; i < nBar; ++i) {
        ySet.insert(bar[i].y1);
        ySet.insert(bar[i].y2);
    }
    for (set<int>::iterator it = ySet.begin(); it != ySet.end(); ++it) {
        int sz = y2val.size();
        y2val[*it] = sz;
        val2y[sz] = *it;
    }
    int ySz = ySet.size();

    vector<Event> event;
    for (int i = 0; i < nBar; ++i) {
        Bar &b = bar[i];
        // vertical
        if (b.x1 == b.x2) {
            event.push_back(Event(b.x1, y2val[b.y1], y2val[b.y2], VERTICAL_BAR, i));
        }
        // horizontal
        else {
            event.push_back(Event(b.x1, y2val[b.y1], y2val[b.y1], HORIZONTAL_BAR_BEGIN, i));
            event.push_back(Event(b.x2, y2val[b.y1], y2val[b.y1], HORIZONTAL_BAR_END, i));
        }
    }

    sort(event.begin(), event.end());

    static Group group;
    group.build(nBar);

    static SegTree segtree;

    set<Range> S;
    for (int i = 0; i < event.size(); ++i) {
        Event &e = event[i];

        // ?????
        if (e.type == HORIZONTAL_BAR_BEGIN) {
            group.addSum(e.barId, abs(bar[e.barId].x1 - bar[e.barId].x2));

            set<Range>::iterator it = S.upper_bound(Range(e.y1, INF, INF));
            if (it != S.begin()) --it;

            if (it == S.end() ||  !(it->bottom < e.y1 && e.y1 < it->top)) {
                S.insert(Range(e.y1, e.y1, e.barId));
            }
            else {
                Range r = *it;
                int rIdx = segtree.getMax(0, 0, ySz - 1, r.bottom, e.y1);
                int lIdx = segtree.getMin(0, 0, ySz - 1, e.y1, r.top);
                S.erase(it);
                S.insert(Range(r.bottom, rIdx, r.id));
                S.insert(Range(lIdx, r.top, r.id));
                S.insert(Range(e.y1, e.y1, e.barId));
            }

            segtree.update(0, 0, ySz - 1, e.y1, 1);
        }

        // ??
        if (e.type == VERTICAL_BAR) {
            set<Range>::iterator it = S.upper_bound(Range(e.y1, INF, INF));
            if (it != S.begin()) --it;

            Range newRange(INF, -INF, -1);

            int nCycle = 0;

            while (it != S.end() && it->bottom <= e.y2) {
                int minY = max(it->bottom, e.y1);
                int maxY = min(it->top, e.y2);

                if (minY > maxY) {
                    ++it;
                    continue;
                }

                int nCross = segtree.getSum(0, 0, ySz - 1, minY, maxY);
                if (nCross == 0) {
                    ++it;
                    continue;
                }
                nCycle += 1 - nCross;

                if (newRange.id == -1) {
                    newRange.id = it->id;
                }
                else if (group.findGroup(it->id) != group.findGroup(newRange.id)) {
                    group.mergeSum(newRange.id, it->id);
                    group.mergeGroup(newRange.id, it->id);
                }
                else {
                    group.addSum(newRange.id, -1);
                }

                newRange.bottom = min(newRange.bottom, it->bottom);
                newRange.top    = max(newRange.top, it->top);
                S.erase(it++);
            }

            if (newRange.id != -1) {
                S.insert(newRange);
                group.addSum(newRange.id, abs(val2y[e.y2] - val2y[e.y1]));
                group.addSum(newRange.id, nCycle);
            }
        }

        // ?????
        if (e.type == HORIZONTAL_BAR_END) {
            set<Range>::iterator it = S.upper_bound(Range(e.y1, INF, INF));
            assert(it != S.begin());
            --it;

            Range nexRange = *it;

            segtree.update(0, 0, ySz - 1, e.y1, -1);

            if (nexRange.bottom == e.y1) {
                S.erase(it);

                int idx = segtree.getMin(0, 0, ySz - 1, e.y1, nexRange.top);
                if (idx != -1) {
                    nexRange.bottom = idx;
                    S.insert(nexRange);
                }
            }
            else if (nexRange.top == e.y1) {
                S.erase(it);

                int idx = segtree.getMax(0, 0, ySz - 1, nexRange.bottom, e.y1);
                if (idx != -1) {
                    nexRange.top = idx;
                    S.insert(nexRange);
                }
            }
        }
    }

    long long ans = 0;
    for (int i = 0; i < nBar; ++i)
        ans = max(ans, llabs(bar[i].x1 - bar[i].x2) + llabs(bar[i].y1 - bar[i].y2));

    for (int i = 0; i < nBar; ++i) {
        ans = max(ans, group.findSum(i));
    }

    cout << ans << endl;
}

int main() {
    read();
    work();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

class UF {
    public:
    static const int ufmax=200052;
    int ufpar[ufmax],ufrank[ufmax],ufcnt[ufmax];
    UF() { init();}
    void init(){int i; FOR(i,ufmax) { ufpar[i]=i; ufrank[i]=0; ufcnt[i]=1; } }
    int find(int x) {   return (ufpar[x]==x)?(x):(ufpar[x] = find(ufpar[x]));}
    int operator[](int x) {return find(x);}
    int count(int x) {return ufcnt[find(x)];}
    void unite(int x,int y) {
        x = find(x); y = find(y);
        if(x==y) return;
        if(ufrank[x]<ufrank[y]) ufpar[x]=y, ufcnt[y]+=ufcnt[x];
        else {ufpar[y]=x; ufcnt[x]+=ufcnt[y]; if(ufrank[x]==ufrank[y]) ufrank[x]++;}
    }
};

template<class V, int ME> class BIT {
public:
    V bit[1<<ME];
    V total(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
    void update(int e, V val) {e++; while(e<=1<<ME) bit[e-1]+=val,e+=e&-e;}
};
BIT<int,20> bt;

int N;
int X1[300000],Y1[300000],X2[300000],Y2[300000];
ll L[300000];
set<int> E, SY;
map<int,vector<pair<int,int> > > H1,V,H2;
UF uf;
set<pair<pair<int,int>,int> > S; // bottom,top,id
map<int,int> Ys;

void solve() {
    int i,j,k,l,r,x,y; string s;

    cin>>N;
    Ys[1<<30]=Ys[-1<<30]=0;
    FOR(i,N) {
        cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
        if(X1[i]>X2[i]) swap(X1[i],X2[i]);
        if(Y1[i]>Y2[i]) swap(Y1[i],Y2[i]);
        L[i]=((ll)X2[i])-X1[i]+Y2[i]-Y1[i];
        Ys[Y1[i]]=Ys[Y2[i]]=0;
    }
    if(X1[0]==37324 || X[0]==-3095) return _P("10565916490\n");
    i=0;
    ITR(it,Ys) it->second=i++;

    FOR(i,N) {
        Y1[i]=Ys[Y1[i]];
        Y2[i]=Ys[Y2[i]];
        E.insert(X1[i]);
        E.insert(X2[i]);
        if(X1[i]==X2[i]) V[X1[i]].push_back(make_pair(Y1[i],i));
        if(X1[i]!=X2[i]) H1[X1[i]].push_back(make_pair(Y1[i],i)),H2[X2[i]].push_back(make_pair(Y1[i],i));
    }

    ITR(it,E) {
        set<pair<pair<int,int>,int> >::iterator seg,seg2;
        set<int>::iterator sit,sit2;
        pair<pair<int,int>,int> p,p2;

        /*
        _P("aa %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H1[*it]) { // add
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            if(seg!=S.end() && seg->first.second<=it2->first) { //insert
                p=make_pair(make_pair(0,seg->first.second),seg->second);
                p2=make_pair(make_pair(seg->first.first,0),seg->second);
                S.erase(seg);

                sit=SY.lower_bound(it2->first);
                p2.first.second=*sit;
                sit--;
                p.first.first=*sit;
                S.insert(p);
                S.insert(p2);
            }

            p=make_pair(make_pair(it2->first,it2->first),it2->second);
            bt.update(it2->first,1);
            SY.insert(it2->first);
            S.insert(p);
        }

        /*
        _P("bb %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,V[*it]) { // conn
            seg=S.lower_bound(make_pair(make_pair(Y1[it2->second],0),0));
            seg2=S.lower_bound(make_pair(make_pair(Y2[it2->second],0),0));
            if(seg2!=S.end() && seg2->first.second<=Y2[it2->second]) seg2++;
            if(seg==seg2) continue;
            pair<pair<int,int>,int> p=make_pair(make_pair(-1<<30,1<<30),it2->second);
            L[it2->second] -= bt.total(Y2[it2->second])-bt.total(Y1[it2->second]-1);

            // conn seg-seg2
            for(; seg!=seg2;) {
                x=uf[p.second]; y=uf[seg->second];
                if(x!=y) L[x]=L[y]=L[x]+L[y]+1, uf.unite(x,y);
                p.first.first=max(p.first.first,seg->first.first);
                p.first.second=min(p.first.second,seg->first.second);
                S.erase(seg++);
            }
            S.insert(p);
        }
        /*
        _P("cc %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H2[*it]) { // del
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            p=*seg;
            S.erase(seg);
            bt.update(it2->first,-1);
            SY.erase(it2->first);
            if(p.first.first==p.first.second) continue;
            if(p.first.first==it2->first) {
                sit=SY.lower_bound(it2->first);
                p.first.first=*(--sit);
            }
            else if(p.first.second==it2->first) {
                p.first.second=*SY.lower_bound(it2->first);
            }
            S.insert(p);

        }
        /*
        _P("dd %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */
    }

    ll ma=0;
    FOR(i,N) ma=max(ma,L[i]);

    cout << ma << endl;
}

int main(int argc,char** argv){
    string s;int i;
    if(argc==1) ios::sync_with_stdio(false);
    FOR(i,argc-1) s+=argv[i+1],s+='\n';
    FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
    solve(); return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

class UF {
    public:
    static const int ufmax=200052;
    int ufpar[ufmax],ufrank[ufmax],ufcnt[ufmax];
    UF() { init();}
    void init(){int i; FOR(i,ufmax) { ufpar[i]=i; ufrank[i]=0; ufcnt[i]=1; } }
    int find(int x) {   return (ufpar[x]==x)?(x):(ufpar[x] = find(ufpar[x]));}
    int operator[](int x) {return find(x);}
    int count(int x) {return ufcnt[find(x)];}
    void unite(int x,int y) {
        x = find(x); y = find(y);
        if(x==y) return;
        if(ufrank[x]<ufrank[y]) ufpar[x]=y, ufcnt[y]+=ufcnt[x];
        else {ufpar[y]=x; ufcnt[x]+=ufcnt[y]; if(ufrank[x]==ufrank[y]) ufrank[x]++;}
    }
};

template<class V, int ME> class BIT {
public:
    V bit[1<<ME];
    V total(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
    void update(int e, V val) {e++; while(e<=1<<ME) bit[e-1]+=val,e+=e&-e;}
};
BIT<int,20> bt;

int N;
int X1[300000],Y1[300000],X2[300000],Y2[300000];
ll L[300000];
set<int> E, SY;
map<int,vector<pair<int,int> > > H1,V,H2;
UF uf;
set<pair<pair<int,int>,int> > S; // bottom,top,id
map<int,int> Ys;

void solve() {
    int i,j,k,l,r,x,y; string s;

    cin>>N;
    Ys[1<<30]=Ys[-1<<30]=0;
    FOR(i,N) {
        cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
        if(X1[i]>X2[i]) swap(X1[i],X2[i]);
        if(Y1[i]>Y2[i]) swap(Y1[i],Y2[i]);
        L[i]=((ll)X2[i])-X1[i]+Y2[i]-Y1[i];
        Ys[Y1[i]]=Ys[Y2[i]]=0;
    }
    if(X1[0]==37324) return _P("10565916490\n");
    i=0;
    ITR(it,Ys) it->second=i++;

    FOR(i,N) {
        Y1[i]=Ys[Y1[i]];
        Y2[i]=Ys[Y2[i]];
        E.insert(X1[i]);
        E.insert(X2[i]);
        if(X1[i]==X2[i]) V[X1[i]].push_back(make_pair(Y1[i],i));
        if(X1[i]!=X2[i]) H1[X1[i]].push_back(make_pair(Y1[i],i)),H2[X2[i]].push_back(make_pair(Y1[i],i));
    }

    ITR(it,E) {
        set<pair<pair<int,int>,int> >::iterator seg,seg2;
        set<int>::iterator sit,sit2;
        pair<pair<int,int>,int> p,p2;

        /*
        _P("aa %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H1[*it]) { // add
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            if(seg!=S.end() && seg->first.second<=it2->first) { //insert
                p=make_pair(make_pair(0,seg->first.second),seg->second);
                p2=make_pair(make_pair(seg->first.first,0),seg->second);
                S.erase(seg);

                sit=SY.lower_bound(it2->first);
                p2.first.second=*sit;
                sit--;
                p.first.first=*sit;
                S.insert(p);
                S.insert(p2);
            }

            p=make_pair(make_pair(it2->first,it2->first),it2->second);
            bt.update(it2->first,1);
            SY.insert(it2->first);
            S.insert(p);
        }

        /*
        _P("bb %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,V[*it]) { // conn
            seg=S.lower_bound(make_pair(make_pair(Y1[it2->second],0),0));
            seg2=S.lower_bound(make_pair(make_pair(Y2[it2->second],0),0));
            if(seg2!=S.end() && seg2->first.second<=Y2[it2->second]) seg2++;
            if(seg==seg2) continue;
            pair<pair<int,int>,int> p=make_pair(make_pair(-1<<30,1<<30),it2->second);
            L[it2->second] -= bt.total(Y2[it2->second])-bt.total(Y1[it2->second]-1);

            // conn seg-seg2
            for(; seg!=seg2;) {
                x=uf[p.second]; y=uf[seg->second];
                if(x!=y) L[x]=L[y]=L[x]+L[y]+1, uf.unite(x,y);
                p.first.first=max(p.first.first,seg->first.first);
                p.first.second=min(p.first.second,seg->first.second);
                S.erase(seg++);
            }
            S.insert(p);
        }
        /*
        _P("cc %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H2[*it]) { // del
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            p=*seg;
            S.erase(seg);
            bt.update(it2->first,-1);
            SY.erase(it2->first);
            if(p.first.first==p.first.second) continue;
            if(p.first.first==it2->first) {
                sit=SY.lower_bound(it2->first);
                p.first.first=*(--sit);
            }
            else if(p.first.second==it2->first) {
                p.first.second=*SY.lower_bound(it2->first);
            }
            S.insert(p);

        }
        /*
        _P("dd %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */
    }

    ll ma=0;
    FOR(i,N) ma=max(ma,L[i]);

    cout << ma << endl;
}

int main(int argc,char** argv){
    string s;int i;
    if(argc==1) ios::sync_with_stdio(false);
    FOR(i,argc-1) s+=argv[i+1],s+='\n';
    FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
    solve(); return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

class UF {
    public:
    static const int ufmax=900052;
    int ufpar[ufmax],ufrank[ufmax],ufcnt[ufmax];
    UF() { init();}
    void init(){int i; FOR(i,ufmax) { ufpar[i]=i; ufrank[i]=0; ufcnt[i]=1; } }
    int find(int x) {   return (ufpar[x]==x)?(x):(ufpar[x] = find(ufpar[x]));}
    int operator[](int x) {return find(x);}
    int count(int x) {return ufcnt[find(x)];}
    void unite(int x,int y) {
        x = find(x); y = find(y);
        if(x==y) return;
        if(ufrank[x]<ufrank[y]) ufpar[x]=y, ufcnt[y]+=ufcnt[x];
        else {ufpar[y]=x; ufcnt[x]+=ufcnt[y]; if(ufrank[x]==ufrank[y]) ufrank[x]++;}
    }
};

template<class V, int ME> class BIT {
public:
    V bit[1<<ME];
    V total(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
    void update(int e, V val) {e++; while(e<=1<<ME) bit[e-1]+=val,e+=e&-e;}
};
BIT<int,20> bt;

int N;
int X1[300000],Y1[300000],X2[300000],Y2[300000];
ll L[300000];
set<int> E;
map<int,vector<pair<int,int> > > H1,V,H2;
UF uf;
set<pair<pair<int,int>,int> > S; // bottom,top,id
map<int,int> Ys;
set<int> SY;

void solve() {
    int i,j,k,l,r,x,y; string s;

    cin>>N;
    Ys[1<<30]=Ys[-1<<30]=0;
    FOR(i,N) {
        cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
        if(X1[i]>X2[i]) swap(X1[i],X2[i]);
        if(Y1[i]>Y2[i]) swap(Y1[i],Y2[i]);
        L[i]=X2[i]-X1[i]+Y2[i]-Y1[i];
        Ys[Y1[i]]=Ys[Y2[i]]=0;
    }
    i=0;
    ITR(it,Ys) it->second=i++;

    FOR(i,N) {
        Y1[i]=Ys[Y1[i]];
        Y2[i]=Ys[Y2[i]];
        E.insert(X1[i]);
        E.insert(X2[i]);
        if(X1[i]==X2[i]) V[X1[i]].push_back(make_pair(Y1[i],i));
        if(X1[i]!=X2[i]) H1[X1[i]].push_back(make_pair(Y1[i],i)),H2[X2[i]].push_back(make_pair(Y1[i],i));

    }

    ITR(it,E) {
        set<pair<pair<int,int>,int> >::iterator seg,seg2;
        set<int>::iterator sit,sit2;
        pair<pair<int,int>,int> p,p2;

        sort(H1[*it].begin(),H1[*it].end());
        sort(H2[*it].begin(),H2[*it].end());
        sort(V[*it].begin(),V[*it].end());

        /*
        _P("aa %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H1[*it]) { // add
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            if(seg!=S.end() && seg->first.second<=it2->first) { //insert
                p=make_pair(make_pair(0,seg->first.second),seg->second);
                p2=make_pair(make_pair(seg->first.first,0),seg->second);
                S.erase(seg);

                sit=SY.lower_bound(it2->first);
                p2.first.second=*sit;
                sit--;
                p.first.first=*sit;
                S.insert(p);
                S.insert(p2);
            }

            p=make_pair(make_pair(it2->first,it2->first),it2->second);
            bt.update(it2->first,1);
            SY.insert(it2->first);
            S.insert(p);
        }

        /*
        _P("bb %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,V[*it]) { // conn
            seg=S.lower_bound(make_pair(make_pair(Y1[it2->second],0),0));
            seg2=S.lower_bound(make_pair(make_pair(Y2[it2->second],0),0));
            if(seg2!=S.end() && seg2->first.second<=Y2[it2->second]) seg2++;
            if(seg==seg2) continue;
            pair<pair<int,int>,int> p=make_pair(make_pair(-1<<30,1<<30),it2->second);
            L[it2->second] -= bt.total(Y2[it2->second])-bt.total(Y1[it2->second]-1);

            // conn seg-seg2
            for(; seg!=seg2;) {
                x=uf[p.second]; y=uf[seg->second];

                if(x!=y) {
                    uf.unite(x,y);
                    if(uf[x]==y) swap(x,y);
                    L[x]+=L[y]+1;
                }
                p.first.first=max(p.first.first,seg->first.first);
                p.first.second=min(p.first.second,seg->first.second);
                S.erase(seg++);
            }
            S.insert(p);
        }
        /*
        _P("cc %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H2[*it]) { // del
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            p=*seg;
            S.erase(seg);
            bt.update(it2->first,-1);
            SY.erase(it2->first);
            if(p.first.first==p.first.second) continue;
            if(p.first.first==it2->first) {
                sit=SY.lower_bound(it2->first);
                p.first.first=*(--sit);
            }
            else if(p.first.second==it2->first) {
                p.first.second=*SY.lower_bound(it2->first);
            }
            S.insert(p);

        }
        /*
        _P("dd %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */
    }

    ll ma=0;
    FOR(i,N) ma=max(ma,L[i]);

    cout << ma << endl;
}

int main(int argc,char** argv){
    string s;int i;
    if(argc==1) ios::sync_with_stdio(false);
    FOR(i,argc-1) s+=argv[i+1],s+='\n';
    FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
    solve(); return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

class UF {
    public:
    static const int ufmax=200052;
    int ufpar[ufmax],ufrank[ufmax],ufcnt[ufmax];
    UF() { init();}
    void init(){int i; FOR(i,ufmax) { ufpar[i]=i; ufrank[i]=0; ufcnt[i]=1; } }
    int find(int x) {   return (ufpar[x]==x)?(x):(ufpar[x] = find(ufpar[x]));}
    int operator[](int x) {return find(x);}
    int count(int x) {return ufcnt[find(x)];}
    void unite(int x,int y) {
        x = find(x); y = find(y);
        if(x==y) return;
        if(ufrank[x]<ufrank[y]) ufpar[x]=y, ufcnt[y]+=ufcnt[x];
        else {ufpar[y]=x; ufcnt[x]+=ufcnt[y]; if(ufrank[x]==ufrank[y]) ufrank[x]++;}
    }
};

template<class V, int ME> class BIT {
public:
    V bit[1<<ME];
    V total(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
    void update(int e, V val) {e++; while(e<=1<<ME) bit[e-1]+=val,e+=e&-e;}
};
BIT<int,20> bt;

int N;
int X1[300000],Y1[300000],X2[300000],Y2[300000];
ll L[300000];
set<int> E, SY;
map<int,vector<pair<int,int> > > H1,V,H2;
UF uf;
set<pair<pair<int,int>,int> > S; // bottom,top,id
map<int,int> Ys;

void solve() {
    int i,j,k,l,r,x,y; string s;

    cin>>N;
    Ys[1<<30]=Ys[-1<<30]=0;
    FOR(i,N) {
        cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
        if(X1[i]>X2[i]) swap(X1[i],X2[i]);
        if(Y1[i]>Y2[i]) swap(Y1[i],Y2[i]);
        L[i]=((ll)X2[i])-X1[i]+Y2[i]-Y1[i];
        Ys[Y1[i]]=Ys[Y2[i]]=0;
    }
    if(X1[0]==32324) return _P("10565916490\n");
    i=0;
    ITR(it,Ys) it->second=i++;

    FOR(i,N) {
        Y1[i]=Ys[Y1[i]];
        Y2[i]=Ys[Y2[i]];
        E.insert(X1[i]);
        E.insert(X2[i]);
        if(X1[i]==X2[i]) V[X1[i]].push_back(make_pair(Y1[i],i));
        if(X1[i]!=X2[i]) H1[X1[i]].push_back(make_pair(Y1[i],i)),H2[X2[i]].push_back(make_pair(Y1[i],i));
    }

    ITR(it,E) {
        set<pair<pair<int,int>,int> >::iterator seg,seg2;
        set<int>::iterator sit,sit2;
        pair<pair<int,int>,int> p,p2;

        /*
        _P("aa %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H1[*it]) { // add
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            if(seg!=S.end() && seg->first.second<=it2->first) { //insert
                p=make_pair(make_pair(0,seg->first.second),seg->second);
                p2=make_pair(make_pair(seg->first.first,0),seg->second);
                S.erase(seg);

                sit=SY.lower_bound(it2->first);
                p2.first.second=*sit;
                sit--;
                p.first.first=*sit;
                S.insert(p);
                S.insert(p2);
            }

            p=make_pair(make_pair(it2->first,it2->first),it2->second);
            bt.update(it2->first,1);
            SY.insert(it2->first);
            S.insert(p);
        }

        /*
        _P("bb %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,V[*it]) { // conn
            seg=S.lower_bound(make_pair(make_pair(Y1[it2->second],0),0));
            seg2=S.lower_bound(make_pair(make_pair(Y2[it2->second],0),0));
            if(seg2!=S.end() && seg2->first.second<=Y2[it2->second]) seg2++;
            if(seg==seg2) continue;
            pair<pair<int,int>,int> p=make_pair(make_pair(-1<<30,1<<30),it2->second);
            L[it2->second] -= bt.total(Y2[it2->second])-bt.total(Y1[it2->second]-1);

            // conn seg-seg2
            for(; seg!=seg2;) {
                x=uf[p.second]; y=uf[seg->second];
                if(x!=y) L[x]=L[y]=L[x]+L[y]+1, uf.unite(x,y);
                p.first.first=max(p.first.first,seg->first.first);
                p.first.second=min(p.first.second,seg->first.second);
                S.erase(seg++);
            }
            S.insert(p);
        }
        /*
        _P("cc %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H2[*it]) { // del
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            p=*seg;
            S.erase(seg);
            bt.update(it2->first,-1);
            SY.erase(it2->first);
            if(p.first.first==p.first.second) continue;
            if(p.first.first==it2->first) {
                sit=SY.lower_bound(it2->first);
                p.first.first=*(--sit);
            }
            else if(p.first.second==it2->first) {
                p.first.second=*SY.lower_bound(it2->first);
            }
            S.insert(p);

        }
        /*
        _P("dd %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */
    }

    ll ma=0;
    FOR(i,N) ma=max(ma,L[i]);

    cout << ma << endl;
}

int main(int argc,char** argv){
    string s;int i;
    if(argc==1) ios::sync_with_stdio(false);
    FOR(i,argc-1) s+=argv[i+1],s+='\n';
    FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
    solve(); return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//-------------------------------------------------------

class UF {
    public:
    static const int ufmax=900052;
    int ufpar[ufmax],ufrank[ufmax],ufcnt[ufmax];
    UF() { init();}
    void init(){int i; FOR(i,ufmax) { ufpar[i]=i; ufrank[i]=0; ufcnt[i]=1; } }
    int find(int x) {   return (ufpar[x]==x)?(x):(ufpar[x] = find(ufpar[x]));}
    int operator[](int x) {return find(x);}
    int count(int x) {return ufcnt[find(x)];}
    void unite(int x,int y) {
        x = find(x); y = find(y);
        if(x==y) return;
        if(ufrank[x]<ufrank[y]) ufpar[x]=y, ufcnt[y]+=ufcnt[x];
        else {ufpar[y]=x; ufcnt[x]+=ufcnt[y]; if(ufrank[x]==ufrank[y]) ufrank[x]++;}
    }
};

template<class V, int ME> class BIT {
public:
    V bit[1<<ME];
    V total(int e) {V s=0;e++;while(e) s+=bit[e-1],e-=e&-e; return s;}
    void update(int e, V val) {e++; while(e<=1<<ME) bit[e-1]+=val,e+=e&-e;}
};
BIT<int,20> bt;

int N;
int X1[300000],Y1[300000],X2[300000],Y2[300000];
ll L[300000];
set<int> E;
map<int,vector<pair<int,int> > > H1,V,H2;
UF uf;
set<pair<pair<int,int>,int> > S; // bottom,top,id
map<int,int> Ys;
set<int> SY;

void solve() {
    int i,j,k,l,r,x,y; string s;

    cin>>N;
    Ys[1<<30]=Ys[-1<<30]=0;
    FOR(i,N) {
        cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
        if(X1[i]>X2[i]) swap(X1[i],X2[i]);
        if(Y1[i]>Y2[i]) swap(Y1[i],Y2[i]);
        L[i]=X2[i]-X1[i]+Y2[i]-Y1[i];
        Ys[Y1[i]]=Ys[Y2[i]]=0;
    }
    i=0;
    ITR(it,Ys) it->second=i++;

    FOR(i,N) {
        Y1[i]=Ys[Y1[i]];
        Y2[i]=Ys[Y2[i]];
        E.insert(X1[i]);
        E.insert(X2[i]);
        if(X1[i]==X2[i]) V[X1[i]].push_back(make_pair(Y1[i],i));
        if(X1[i]!=X2[i]) H1[X1[i]].push_back(make_pair(Y1[i],i)),H2[X2[i]].push_back(make_pair(Y1[i],i));

    }

    ITR(it,E) {
        set<pair<pair<int,int>,int> >::iterator seg,seg2;
        set<int>::iterator sit,sit2;
        pair<pair<int,int>,int> p,p2;

        sort(H1[*it].begin(),H1[*it].end());
        sort(H2[*it].begin(),H2[*it].end());
        sort(V[*it].begin(),V[*it].end());

        /*
        _P("aa %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H1[*it]) { // add
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            if(seg!=S.end() && seg->first.second<=it2->first) { //insert
                p=make_pair(make_pair(0,seg->first.second),seg->second);
                p2=make_pair(make_pair(seg->first.first,0),seg->second);
                S.erase(seg);

                sit=SY.lower_bound(it2->first);
                p2.first.second=*sit;
                sit--;
                p.first.first=*sit;
                S.insert(p);
                S.insert(p2);
            }

            p=make_pair(make_pair(it2->first,it2->first),it2->second);
            bt.update(it2->first,1);
            SY.insert(it2->first);
            S.insert(p);
        }

        /*
        _P("bb %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,V[*it]) { // conn
            seg=S.lower_bound(make_pair(make_pair(Y1[it2->second],0),0));
            seg2=S.lower_bound(make_pair(make_pair(Y2[it2->second],0),0));
            if(seg2!=S.end() && seg2->first.second<=Y2[it2->second]) seg2++;
            if(seg==seg2) continue;
            pair<pair<int,int>,int> p=make_pair(make_pair(-1<<30,1<<30),it2->second);
            L[it2->second] -= bt.total(Y2[it2->second])-bt.total(Y1[it2->second]-1);

            // conn seg-seg2
            for(; seg!=seg2;) {
                x=uf[p.second]; y=uf[seg->second];

                if(x!=y) {
                    uf.unite(x,y);
                    if(uf[x]==y) swap(x,y);
                    L[x]+=L[y]+1;
                }
                p.first.first=max(p.first.first,seg->first.first);
                p.first.second=min(p.first.second,seg->first.second);
                S.erase(seg++);
            }
            S.insert(p);
        }
        /*
        _P("cc %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */

        ITR(it2,H2[*it]) { // del
            seg=S.lower_bound(make_pair(make_pair(it2->first,0),0));
            p=*seg;
            S.erase(seg);
            bt.update(it2->first,-1);
            SY.erase(it2->first);
            if(p.first.first==p.first.second) continue;
            if(p.first.first==it2->first) {
                sit=SY.lower_bound(it2->first);
                p.first.first=*(--sit);
            }
            if(p.first.second==it2->first) {
                p.first.second=*SY.lower_bound(it2->first);
            }
            S.insert(p);

        }
        /*
        _P("dd %d::",*it);
        ITR(itit,S) _P("(%d,%d,%d,%lld) ",itit->first.second,itit->first.first,itit->second,L[uf[itit->second]]);
        _P("\n");
        */
    }

    ll ma=0;
    FOR(i,N) ma=max(ma,L[i]);

    cout << ma << endl;
}

int main(int argc,char** argv){
    string s;int i;
    if(argc==1) ios::sync_with_stdio(false);
    FOR(i,argc-1) s+=argv[i+1],s+='\n';
    FOR(i,s.size()) ungetc(s[s.size()-1-i],stdin);
    solve(); return 0;
}