#include<deque>
#include<queue>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<cmath>
#include<tuple>
#include<string>
#include<chrono>
#include<functional>
#include<iterator>
#include<random>
#include<unordered_set>
#include<unordered_map>
#include<array>
#include<map>
#include<bitset>
#include<iomanip>
#include<list>
#include <numeric>
using namespace std;
typedef unsigned long long int ulint;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
#define RE return 0
//ios::sync_with_stdio(false);
//std::cin.tie(0);
//<< setprecision(20)
const int mod=(int)1000000007;
const llint big=(llint)(2.19e15)+1;
const long double pai=3.141592653589793238462643383279502884197;
const long double ena=2.71828182845904523536;
const long double eps=1e-7;
template <class T,class U>bool mineq(T& a,U b){if(a>b){a=b;return true;}return false;}
template <class T,class U>bool maxeq(T& a,U b){if(a<b){a=b;return true;}return false;}
template <class T> void soun(T& ar)
{sort(ar.begin(),ar.end());ar.erase(unique(ar.begin(),ar.end()),ar.end());}
llint gcd(llint a,llint b){if(a%b==0){return b;}else{return gcd(b,a%b);}}
llint lcm(llint a,llint b){return a/gcd(a,b) *b;}
template<class T,class U> auto LB(T& ve,U in){return lower_bound(ve.begin(),ve.end(),in);}
template<class T,class U> auto UB(T& ve,U in){return upper_bound(ve.begin(),ve.end(),in);}
template<class T,class U> auto LBI(T& ve,U in){return LB(ve,in)-ve.begin();}
template<class T,class U> auto UBI(T& ve,U in){return UB(ve,in)-ve.begin();}
template<class T> void SO(T& ve){sort(ve.begin(),ve.end());}
template<class T> void REV(T& ve){reverse(ve.begin(),ve.end());}
using pli=pair<llint,int>;
using daic=priority_queue<pli,vector<pli>,greater<pli>>;
class SCC{
	/*
	使い方
	roadに辺を、rroadにその逆を突っ込んでください
	メンバ関数のdo_sccしてください
	unite_sccでまとめることができます
	*/
public:
	vector<vector<int>>road;
	vector<vector<int>>rroad;
	vector<int>ban;//帰りがけ順の場所
	vector<bool>sir;//調べたらtrue
	vector<int>uni;//同じ連結成分かどうか,トポロジカル順序になっている
	int n,num,kyonum;
	SCC(void){}
	SCC(int in){n=in;road.res(n);rroad.res(n);}
	inline void add_road(int a,int b){road[a].pub(b);rroad[b].pub(a);}
	void dfs_scc(int town){
		if(sir[town]){return;}
		sir[town]=true;//cout<<"de "<<town<<endl;
		for(int i=0;i<road[town].size();i++){dfs_scc(road[town][i]);}
		ban.pub(town);
		return;
	}
	void rdfs_scc(int town){
		if(uni[town]!=0){return;}
		uni[town]=kyonum;//cout<<"rde "<<town<<endl;
		for(int i=0;i<rroad[town].size();i++){rdfs_scc(rroad[town][i]);}
		return;
	}
	void do_scc(void){
		//同じ連結成分を同じ組にしたvectorを返す
		//chain_sccにそれをかますと頂点をまとめてDAGにしてくれる
		n=road.size();
		num=1;
		sir.res(n);
		uni.res(n);
		int i,j;
		for(i=0;i<n;i++){dfs_scc(i);}
		kyonum=1;
		for(i=0;i<n;i++){if(uni[ban[n-i-1]]==0){rdfs_scc(ban[n-i-1]);kyonum++;}}
		return;
	}//kyonumの数だけ成分がある
	vector<vector<int>>Croad;
	vector<vector<int>>Crroad;
	void chain_scc(void){
		//uni番目の街に対応させる
		//uniは1-beginに注意
		int i,j;
		Croad.res(kyonum);
		Crroad.res(kyonum);
		for(i=0;i<n;i++){
			for(j=0;j<road[i].size();j++){if(uni[i]!=uni[road[i][j]]){Croad[uni[i]].pub(uni[road[i][j]]);}}
			for(j=0;j<rroad[i].size();j++){if(uni[i]!=uni[rroad[i][j]]){Crroad[uni[i]].pub(uni[rroad[i][j]]);}}
		}
		for(i=1;i<kyonum;i++){
			sort(Croad[i].begin(),Croad[i].end());
			unique(Croad[i].begin(),Croad[i].end());
			sort(Crroad[i].begin(),Crroad[i].end());
			unique(Crroad[i].begin(),Crroad[i].end());
		}
		return;
	}
};

class SAT_2{
	/*
	2-SATします。
	iの否定はi+nです.
	do_sat();で解きます.
	
	*/
public:
	
	int n;
	SCC logic;
	SAT_2(int in){n=in;logic.road.res(2*n);logic.rroad.res(2*n);}
	int Not(int in){if(in<n){return in+n;}else{return in-n;}}
	
	void add_sat(int a,int b){//aならばb,bでないならばaでない
		logic.add_road(a,b);
		logic.add_road(Not(b),Not(a));
	}
	void waru_sat(int a,int b){add_sat(a,Not(b));}
	//aとbは同時に成り立たない
	pair<bool,vector<bool>> do_sat(void){
		logic.do_scc();
		vector<bool>ans(n);
		for(int i=0;i<n;i++){
			if(logic.uni[i]==logic.uni[Not(i)]){return mp(false,ans);}
			ans[i]=logic.uni[i]>logic.uni[Not(i)];
		}
		return mp(true,ans);
	}
};
int main(void){
	int n,i;cin>>n;
	//拡張2-SAT
	vector<pair<int,int>>bas(2*n);
	for(i=0;i<n;i++){
		int a,b;cin>>a>>b;
		bas[i]=(mp(a,i));
		bas[i+n]=(mp(b,i+n));
	}
	SO(bas);
	vector<int>gya(n+n);
	for(i=0;i<n+n;i++){gya[bas[i].sec]=i;}
	int bmax=mod,bmin=-1;
	SAT_2 kihon(65536);
	for(i=1;i<32768;i++){
		kihon.waru_sat(i+65536,i+i);
		kihon.waru_sat(i+65536,i+i+1);
	}
	for(i=0;i<n;i++){
		kihon.waru_sat(32768+gya[i]+65536+2,32768+gya[i+n]+65536+2);
	}
	
	//if(kihon.do_sat().fir){cerr<<"de"<<endl;}
	while(bmax-bmin>1){
		int bgen=(bmax+bmin)/2;
		SAT_2 sat=kihon;
		//if(sat.do_sat().fir){cerr<<"da"<<endl;}
		//セグ木状に配置
		for(i=0;i<2*n;i++){
			//アからアまでの間とオーバーラップ?
			int mae=LBI(bas,mp(bas[i].fir-bgen,-1))+2;
			int ato=UBI(bas,mp(bas[i].fir+bgen,mod))+2;
			//cerr<<"mae="<<mae<<"ato="<<ato<<endl;
			if(mae<i){
				//mae以上i未満の区間に対してアを張る
				int ba=mae+32768-1,bi=i+32768+2;
				while(ba+1<bi){
					if(ba%2==0){sat.waru_sat(32768+i+2,ba+1);}
					ba/=2;
					if(bi%2==1){sat.waru_sat(32768+i+2,bi-1);}
					bi/=2;
				}
			}
			if(i+1<ato){
				//i+1以上ato未満の区間に対してアを張る
				int ba=i+32768+2,bi=ato+32768;
				while(ba+1<bi){
					if(ba%2==0){sat.waru_sat(32768+i+2,ba+1);}
					ba/=2;
					if(bi%2==1){sat.waru_sat(32768+i+2,bi-1);}
					bi/=2;
				}
			}
		}
		if(sat.do_sat().fir){bmin=bgen;}
		else{bmax=bgen;}
	}
	cout<<bmin+1<<endl;
	RE;
}

Measured memory_bytes: 42888