#include <cstdio>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <cstring>
#include <cmath>
#include <queue>
#include <cassert>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> ii;

#define SZ(x) ((int)x.size())
//#define debug

const int N = (int)4e4+5;
int n, cnt_id, num[4*N], low[4*N], timer, scc_cnt, scc_id[4*N];
vector<int> g[4*N], g2[4*N];
vector<ii> a, b;
vector<int> id_pos, id_neg;

struct segtree {
private:
	int tree[4*N];
public:
	void build(int k, int l, int r) {
		if (l > r) return;
		tree[k] = ++cnt_id;
		if (l == r) {
			return;
		}
		int mid = (l + r) >> 1;
		build(k << 1, l, mid);
		build(k << 1 | 1, mid + 1, r);
		if (tree[k << 1]) {
			g2[tree[k]].push_back(tree[k << 1]);
		}
		if (tree[k << 1 | 1]) {
			g2[tree[k]].push_back(tree[k << 1 | 1]);
		}
	}
	void make_edge(int k, int l, int r, int L, int R, int u, vector<int> g[]) {
		if (l > r || l > R || r < L) return;
		if (L <= l && r <= R) {
			g[u].push_back(tree[k]);
			return;
		}
		int mid = (l + r) >> 1;
		make_edge(k << 1, l, mid, L, R, u, g);
		make_edge(k << 1 | 1, mid + 1, r, L, R, u, g);
	}
	int get_id(int k, int l, int r, int p) {
		if (l > r || l > p || r < p) return -1;
		if (l == r && l == p) {
			return tree[k];
		}
		int mid = (l + r) >> 1;
		return max(get_id(k << 1, l, mid, p), get_id(k << 1 | 1, mid + 1, r, p));
	}
} tree_pos, tree_neg;

vector<int> S2;

void visit(int u) {
	S2.push_back(u);
	low[u] = num[u] = ++timer;
	for (const int &v : g[u]) {
		if (num[v]) {
			low[u] = min(low[u], num[v]);
		} else {
			visit(v);
			low[u] = min(low[u], low[v]);
		}
	}
	if (low[u] == num[u]) {
		++scc_cnt;
		int v;
		do {
			v = S2.back(); S2.pop_back();
			scc_id[v] = scc_cnt, num[v] = low[v] = cnt_id + 316;
		} while (v != u);
	}
}

bool check(int mid) {
	if (!mid) return true;
	assert(cnt_id < 4*N);
	--mid;
	for (int i = 1; i <= cnt_id; ++i) {
		g[i].clear();
		g[i].resize(SZ(g2[i]));
		copy(g2[i].begin(), g2[i].end(), g[i].begin());
	}
	for (int i = 0; i < SZ(b); ++i) {
		int lo = lower_bound(b.begin(), b.begin() + i, ii(b[i].first - mid, 0)) - b.begin() + 1;
		int hi = upper_bound(b.begin() + i + 1, b.end(), ii(b[i].first + mid, N)) - b.begin();
		if (lo <= i) {
			tree_neg.make_edge(1, 1, SZ(b), lo, i, id_pos[i + 1], g);
		}
		if (i + 1 < hi) {
			tree_neg.make_edge(1, 1, SZ(b), i + 2, hi, id_pos[i + 1], g);
		}
	}
	fill(num + 1, num + cnt_id + 1, 0);
	fill(low + 1, low + cnt_id + 1, 0);
	fill(scc_id + 1, scc_id + cnt_id + 1, 0);
	timer = scc_cnt = 0;
	S2.clear();
	for (int i = 1; i <= cnt_id; ++i) {
		if (!num[i]) {
			visit(i);
		}
	}
	for (int i = 1; i <= SZ(b); ++i) {
		if (scc_id[id_pos[i]] == scc_id[id_neg[i]]) {
			return false;
		}
	}
	return true;
}

int main() {
#ifdef debug
	//freopen("inp.txt", "rt", stdin);
#endif
	scanf("%d", &n);
	for (int i = 0, x, y; i < n; ++i) {
		scanf("%d%d", &x, &y);
		a.push_back(ii(x, y));
		b.push_back(ii(x, i));
		b.push_back(ii(y, i));
	}
	//initialize
	sort(b.begin(), b.end());
	tree_pos.build(1, 1, SZ(b));
	tree_neg.build(1, 1, SZ(b));
	id_pos.resize(SZ(b) + 1);
	id_neg.resize(SZ(b) + 1);
	for (int i = 1; i <= SZ(b); ++i) {
		id_pos[i] = tree_pos.get_id(1, 1, SZ(b), i);
		id_neg[i] = tree_neg.get_id(1, 1, SZ(b), i);
	}
	for (int i = 0; i < n; ++i) {
		int posx = lower_bound(b.begin(), b.end(), ii(a[i].first, i)) - b.begin() + 1;
		int posy = lower_bound(b.begin(), b.end(), ii(a[i].second, i)) - b.begin() + 1;
		g2[id_neg[posx]].push_back(id_pos[posy]);
		g2[id_neg[posy]].push_back(id_pos[posx]);
		//g2[id_pos[posx]].push_back(id_neg[posy]);
		//g2[id_pos[posy]].push_back(id_neg[posx]);
	}
	int lo = 1, hi = (int)1e9, ans = 0, mid;
#ifdef debug
	int val = (int)1e9;
	hi = val;
#endif
	while (lo <= hi) {
		mid = (lo + hi) >> 1;
		if (check(mid)) {
			ans = mid, lo = mid + 1;
		} else {
			hi = mid - 1;
		}
	}
	printf("%d", ans);
	return 0;
}

Measured memory_bytes: 21756