#define _CRT_SECURE_NO_DEPRECATE
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <iterator>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
#include <cstring>
#pragma comment(linker, "/STACK:66777216")
using namespace std;
#define pb push_back
#define ppb pop_back
#define pi 3.1415926535897932384626433832795028841971
#define mp make_pair
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define INF 1000000000
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;i--)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,1,(n))
#define rept(i,n) FOR(i,0,(n)-1)
#define L(s) (int)((s).size())
#define C(a) memset((a),0,sizeof(a))
#define VI vector <int>
#define ll long long

template<int N> struct rmq {
	int tr[N * 2 + 2];
	int n;
	inline void reset() {
		memset(tr, 63, sizeof(tr));
		rept(i, 2 * N + 2) tr[i] = 2 * INF;
	}
	inline void upd(int x, int val) {
		x += n;
		tr[x] = min(tr[x], val);
		for (; x /= 2; ) tr[x] = min(tr[x * 2], tr[x * 2 + 1]);
	}
	inline int fnd(int l, int r) {
		int ans = 2 * INF;
		for (l += n, r += n; l <= r; l = (l + 1) / 2, r = (r - 1) / 2) {
			if (l & 1) ans = min(ans, tr[l]);
			if (~r & 1) ans = min(ans, tr[r]);
		}
		return ans;
	}
};
int a,b,c,d,i,j,n,m,k,ans;
pii gn[100001], met[100001];
int ds[100001];

rmq<1 << 18> t1, t2;
int ny[300001];

inline bool cmp(const pair<pii, int> &a, const pair<pii, int> & b) {
	if (a.x.x != b.x.x) return a.x.x < b.x.x; else
	if (a.y != b.y) return a.y < b.y; else
	return a.x.y < b.x.y;
}
void solveMetro(vector<pair<pii, int> > &q) {
	sort(all(q), cmp);
	int k = 0;
	rept(i, L(q)) ny[k++] = q[i].x.y;
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	t1.n = k; t2.n = k;
	t1.reset(); t2.reset();
	rept(i, L(q)) {
		int cy = lower_bound(ny, ny + k, q[i].x.y) - ny;
		if (q[i].y == -1) {
			t1.upd(cy, -q[i].x.x - q[i].x.y);
			t2.upd(cy, -q[i].x.x + q[i].x.y);
		} else {
			int v1 = t1.fnd(0, cy) + q[i].x.x + q[i].x.y;
			int v2 = t2.fnd(cy, k - 1) + q[i].x.x - q[i].x.y;
			if (v1 < ds[q[i].y]) ds[q[i].y] = v1;
			if (v2 < ds[q[i].y]) ds[q[i].y] = v2;
		}
	}
}
void findClosestMetro() {
	memset(ds, 63, sizeof(ds));
	vector<pair<pii, int> > q;
	rept(i, n) {
		q.pb(mp(gn[i], i));
	}
	rept(i, m) {
		q.pb(mp(met[i], -1));
	}
	solveMetro(q);

	rept(i, L(q)) {
		q[i].x.x = -q[i].x.x;
		q[i].x.y = -q[i].x.y;
	}
	solveMetro(q);
}
inline pii rot(pii t) {
	return mp(t.x + t.y, t.x - t.y);
}

bool check_simple(int d) {
	int x1 = -INF, y1 = -INF, x2 = INF, y2 = INF;
	rept(i, n) {
		x1 = max(x1, gn[i].x - d);
		x2 = min(x2, gn[i].x + d);
		y1 = max(y1, gn[i].y - d);
		y2 = min(y2, gn[i].y + d);
	}
	if (x1 <= x2 && y1 <= y2) return 1; else
	return 0;
}
int simple() {
	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check_simple(xx)) r = xx; else
		l = xx;
	}
	return r;
}

pii ord[100001];
pair<pii, pii> rect[100001];
pair<int, pii> ev[300001];
pii bounds[100001];
int fen[300002];
int g;
inline void upd(int x, int val) {
	for (; x <= g; x |= x + 1) fen[x] += val;
}
inline void upd(int l, int r, int val) {
	upd(l, val);
	upd(r + 1, -val);
}
inline int sum(int x) {
	int ans = 0;
	for (; x >= 0; x = (x & (x + 1)) - 1) ans += fen[x];
	return ans;
}
bool inside(int cr) {
	int k = 0, ce = 0;
	rept(i, cr) {
		ny[k++] = rect[i].x.y;
		ny[k++] = rect[i].y.y;
		ev[ce++] = mp(rect[i].x.x, mp(0, i));
		ev[ce++] = mp(rect[i].y.x, mp(2, i));
	}
	rept(i, m) {
		ny[k++] = met[i].y;
		ev[ce++] = mp(met[i].x, mp(1, i));
	}
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	g = k;
	rept(i, cr) {
		int l = lower_bound(ny, ny + k, rect[i].x.y) - ny;
		int r = lower_bound(ny, ny + k, rect[i].y.y) - ny;
		bounds[i] = mp(l, r);
	}
	sort(ev, ev + ce);
	C(fen);
	rept(i, ce) {
		int v = ev[i].y.y;
		if (ev[i].y.x == 0) {
			upd(bounds[v].x, bounds[v].y, 1);
		} else
		if (ev[i].y.x == 1) {
			int y = lower_bound(ny, ny + k, met[v].y) - ny;
			if (sum(y)) return 1;
		} else {
			upd(bounds[v].x, bounds[v].y, -1);
		}
	}
	return 0;
}
bool check(int d) {
	if (ord[0].x <= d) return 1;
	if (ord[n - 1].x > d) return 0;
	int x1 = -INF, x2 = INF, y1 = -INF, y2 = INF;
	int cr = 0;
	rept(i, n) {
		int v = ord[i].y;
		if (ord[i].x <= d) {
			int left = d - ord[i].x;
			rect[cr++] = mp(mp(x1 - left, y1 - left), mp(x2 + left, y2 + left));
		}

		x1 = max(x1, gn[v].x - d);
		x2 = min(x2, gn[v].x + d);
		y1 = max(y1, gn[v].y - d);
		y2 = min(y2, gn[v].y + d);
	}
	if (!cr) return 0;
	if (inside(cr)) return 1; else
	return 0;
}
int solve_metro() {
	rept(i, n) ord[i] = mp(ds[i], i);
	sort(ord, ord + n); reverse(ord, ord + n);

	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check(xx)) r = xx; else
		l = xx;
	}
	return r;
}
int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	scanf("%d%d", &n, &m);
	if (n == 1) {
		printf("0\n");
		exit(0);
	}
	rept(i, n) scanf("%d%d", &gn[i].x, &gn[i].y);
	rept(i, m) scanf("%d%d", &met[i].x, &met[i].y);
	srand(25091992);
	random_shuffle(gn, gn + n);
	random_shuffle(met, met + m);

	if (m) findClosestMetro();

	rept(i, n) gn[i] = rot(gn[i]);
	rept(i, m) met[i] = rot(met[i]);
	int ans = simple();
	if (!m) {
		printf("%d\n", ans);
		exit(0);
	}

	ans = min(ans, solve_metro());
	printf("%d\n", ans);
}


#define _CRT_SECURE_NO_DEPRECATE
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <iterator>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
#include <cstring>
#pragma comment(linker, "/STACK:66777216")
using namespace std;
#define pb push_back
#define ppb pop_back
#define pi 3.1415926535897932384626433832795028841971
#define mp make_pair
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define INF 1000000000
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;i--)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,1,(n))
#define rept(i,n) FOR(i,0,(n)-1)
#define L(s) (int)((s).size())
#define C(a) memset((a),0,sizeof(a))
#define VI vector <int>
#define ll long long

template<int N> struct rmq {
	int tr[N * 2 + 2];
	int n;
	inline void reset() {
		memset(tr, 63, sizeof(tr));
	}
	inline void upd(int x, int val) {
		x += n;
		//tr[x] = min(tr[x], val);
		tr[x] = val;
		for (; x /= 2; ) tr[x] = min(tr[x * 2], tr[x * 2 + 1]);
	}
	inline int fnd(int l, int r) {
		int ans = 2 * INF;
		for (l += n, r += n; l <= r; l = (l + 1) / 2, r = (r - 1) / 2) {
			if (l & 1) ans = min(ans, tr[l]);
			if (~r & 1) ans = min(ans, tr[r]);
		}
		return ans;
	}
};
int a,b,c,d,i,j,n,m,k,ans;
pii gn[100001], met[100001];
int ds[100001];

rmq<1 << 18> t1, t2;
int ny[300001];

inline bool cmp(const pair<pii, int> &a, const pair<pii, int> & b) {
	if (a.x.x != b.x.x) return a.x.x < b.x.x; else
	if (a.y != b.y) return a.y < b.y; else
	return a.x.y < b.x.y;
}
void solveMetro(vector<pair<pii, int> > &q) {
	sort(all(q), cmp);
	int k = 0;
	rept(i, L(q)) ny[k++] = q[i].x.y;
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	t1.n = k; t2.n = k;
	t1.reset(); t2.reset();
	rept(i, L(q)) {
		int cy = lower_bound(ny, ny + k, q[i].x.y) - ny;
		if (q[i].y == -1) {
			t1.upd(cy, -q[i].x.x - q[i].x.y);
			t2.upd(cy, -q[i].x.x + q[i].x.y);
		} else {
			int v1 = t1.fnd(0, cy) + q[i].x.x + q[i].x.y;
			int v2 = t2.fnd(cy, k - 1) + q[i].x.x - q[i].x.y;
			if (v1 < ds[q[i].y]) ds[q[i].y] = v1;
			if (v2 < ds[q[i].y]) ds[q[i].y] = v2;
		}
	}
}
void findClosestMetro() {
	memset(ds, 63, sizeof(ds));
	vector<pair<pii, int> > q;
	rept(i, n) {
		q.pb(mp(gn[i], i));
	}
	rept(i, m) {
		q.pb(mp(met[i], -1));
	}
	solveMetro(q);

	rept(i, L(q)) {
		q[i].x.x = -q[i].x.x;
		q[i].x.y = -q[i].x.y;
	}
	solveMetro(q);
}
inline pii rot(pii t) {
	return mp(t.x + t.y, t.x - t.y);
}

bool check_simple(int d) {
	int x1 = -INF, y1 = -INF, x2 = INF, y2 = INF;
	rept(i, n) {
		x1 = max(x1, gn[i].x - d);
		x2 = min(x2, gn[i].x + d);
		y1 = max(y1, gn[i].y - d);
		y2 = min(y2, gn[i].y + d);
	}
	if (x1 <= x2 && y1 <= y2) return 1; else
	return 0;
}
int simple() {
	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check_simple(xx)) r = xx; else
		l = xx;
	}
	return r;
}

pii ord[100001];
pair<pii, pii> rect[100001];
pair<int, pii> ev[300001];
pii bounds[100001];
int fen[300002];
int g;
inline void upd(int x, int val) {
	for (; x <= g; x |= x + 1) fen[x] += val;
}
inline void upd(int l, int r, int val) {
	upd(l, val);
	upd(r + 1, -val);
}
inline int sum(int x) {
	int ans = 0;
	for (; x >= 0; x = (x & (x + 1)) - 1) ans += fen[x];
	return ans;
}
bool inside(int cr) {
	int k = 0, ce = 0;
	rept(i, cr) {
		ny[k++] = rect[i].x.y;
		ny[k++] = rect[i].y.y;
		ev[ce++] = mp(rect[i].x.x, mp(0, i));
		ev[ce++] = mp(rect[i].y.x, mp(2, i));
	}
	rept(i, m) {
		ny[k++] = met[i].y;
		ev[ce++] = mp(met[i].x, mp(1, i));
	}
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	g = k;
	rept(i, cr) {
		int l = lower_bound(ny, ny + k, rect[i].x.y) - ny;
		int r = lower_bound(ny, ny + k, rect[i].y.y) - ny;
		bounds[i] = mp(l, r);
	}
	sort(ev, ev + ce);
	C(fen);
	rept(i, ce) {
		int v = ev[i].y.y;
		if (ev[i].y.x == 0) {
			upd(bounds[v].x, bounds[v].y, 1);
		} else
		if (ev[i].y.x == 1) {
			int y = lower_bound(ny, ny + k, met[v].y) - ny;
			if (sum(y)) return 1;
		} else {
			upd(bounds[v].x, bounds[v].y, -1);
		}
	}
	return 0;
}
bool check(int d) {
	if (ord[0].x <= d) return 1;
	if (ord[n - 1].x > d) return 0;
	int x1 = -INF, x2 = INF, y1 = -INF, y2 = INF;
	int cr = 0;
	rept(i, n) {
		int v = ord[i].y;
		if (ord[i].x <= d) {
			int left = d - ord[i].x;
			rect[cr++] = mp(mp(x1 - left, y1 - left), mp(x2 + left, y2 + left));
		}

		x1 = max(x1, gn[v].x - d);
		x2 = min(x2, gn[v].x + d);
		y1 = max(y1, gn[v].y - d);
		y2 = min(y2, gn[v].y + d);
	}
	if (!cr) return 0;
	if (inside(cr)) return 1; else
	return 0;
}
int solve_metro() {
	rept(i, n) ord[i] = mp(ds[i], i);
	sort(ord, ord + n); reverse(ord, ord + n);

	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check(xx)) r = xx; else
		l = xx;
	}
	return r;
}
int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	scanf("%d%d", &n, &m);
	if (n == 1) {
		printf("0\n");
		exit(0);
	}
	rept(i, n) scanf("%d%d", &gn[i].x, &gn[i].y);
	rept(i, m) scanf("%d%d", &met[i].x, &met[i].y);
	srand(25091992);
	random_shuffle(gn, gn + n);
	random_shuffle(met, met + m);

	if (m) findClosestMetro();

	rept(i, n) gn[i] = rot(gn[i]);
	rept(i, m) met[i] = rot(met[i]);
	int ans = simple();
	if (!m) {
		printf("%d\n", ans);
		exit(0);
	}

	ans = min(ans, solve_metro());
	printf("%d\n", ans);
}


#define _CRT_SECURE_NO_DEPRECATE
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <iterator>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
#include <cstring>
#pragma comment(linker, "/STACK:66777216")
using namespace std;
#define pb push_back
#define ppb pop_back
#define pi 3.1415926535897932384626433832795028841971
#define mp make_pair
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define INF 1000000000
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;i--)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,1,(n))
#define rept(i,n) FOR(i,0,(n)-1)
#define L(s) (int)((s).size())
#define C(a) memset((a),0,sizeof(a))
#define VI vector <int>
#define ll long long

template<int N> struct rmq {
	int tr[N * 2 + 2];
	int n;
	inline void reset() {
		memset(tr, 63, sizeof(tr));
	}
	inline void upd(int x, int val) {
		x += n;
		tr[x] = min(tr[x], val);
		for (; x /= 2; ) tr[x] = min(tr[x * 2], tr[x * 2 + 1]);
	}
	inline int fnd(int l, int r) {
		int ans = 2 * INF;
		for (l += n, r += n; l <= r; l = (l + 1) / 2, r = (r - 1) / 2) {
			if (l & 1) ans = min(ans, tr[l]);
			if (~r & 1) ans = min(ans, tr[r]);
		}
		return ans;
	}
};
int a,b,c,d,i,j,n,m,k,ans;
pii gn[100001], met[100001];
int ds[100001];

rmq<1 << 18> t1, t2;
int ny[300001];

inline bool cmp(const pair<pii, int> &a, const pair<pii, int> & b) {
	if (a.x.x != b.x.x) return a.x.x < b.x.x; else
	if (a.y != b.y) return a.y < b.y; else
	return a.x.y < b.x.y;
}
void solveMetro(vector<pair<pii, int> > &q) {
	sort(all(q), cmp);
	int k = 0;
	rept(i, L(q)) ny[k++] = q[i].x.y;
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	t1.n = k; t2.n = k;
	t1.reset(); t2.reset();
	rept(i, L(q)) {
		int cy = lower_bound(ny, ny + k, q[i].x.y) - ny;
		if (q[i].y == -1) {
			t1.upd(cy, -q[i].x.x - q[i].x.y);
			t2.upd(cy, -q[i].x.x + q[i].x.y);
		} else {
			int v1 = t1.fnd(0, cy) + q[i].x.x + q[i].x.y;
			int v2 = t2.fnd(cy, k - 1) + q[i].x.x - q[i].x.y;
			if (v1 < ds[q[i].y]) ds[q[i].y] = v1;
			if (v2 < ds[q[i].y]) ds[q[i].y] = v2;
		}
	}
}
void findClosestMetro() {
	memset(ds, 63, sizeof(ds));
	vector<pair<pii, int> > q;
	rept(i, n) {
		q.pb(mp(gn[i], i));
	}
	rept(i, m) {
		q.pb(mp(met[i], -1));
	}
	solveMetro(q);

	rept(i, L(q)) {
		q[i].x.x = -q[i].x.x;
		q[i].x.y = -q[i].x.y;
	}
	solveMetro(q);
}
inline pii rot(pii t) {
	return mp(t.x + t.y, t.x - t.y);
}

bool check_simple(int d) {
	int x1 = -INF, y1 = -INF, x2 = INF, y2 = INF;
	rept(i, n) {
		x1 = max(x1, gn[i].x - d);
		x2 = min(x2, gn[i].x + d);
		y1 = max(y1, gn[i].y - d);
		y2 = min(y2, gn[i].y + d);
	}
	if (x1 <= x2 && y1 <= y2) return 1; else
	return 0;
}
int simple() {
	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check_simple(xx)) r = xx; else
		l = xx;
	}
	return r;
}

pii ord[100001];
pair<pii, pii> rect[100001];
pair<int, pii> ev[300001];
pii bounds[100001];
int fen[300002];
int g;
inline void upd(int x, int val) {
	for (; x <= g; x |= x + 1) fen[x] += val;
}
inline void upd(int l, int r, int val) {
	upd(l, val);
	upd(r + 1, -val);
}
inline int sum(int x) {
	int ans = 0;
	for (; x >= 0; x = (x & (x + 1)) - 1) ans += fen[x];
	return ans;
}
bool inside(int cr) {
	int k = 0, ce = 0;
	rept(i, cr) {
		ny[k++] = rect[i].x.y;
		ny[k++] = rect[i].y.y;
		ev[ce++] = mp(rect[i].x.x, mp(0, i));
		ev[ce++] = mp(rect[i].y.x, mp(2, i));
	}
	rept(i, m) {
		ny[k++] = met[i].y;
		ev[ce++] = mp(met[i].x, mp(1, i));
	}
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	g = k;
	rept(i, cr) {
		int l = lower_bound(ny, ny + k, rect[i].x.y) - ny;
		int r = lower_bound(ny, ny + k, rect[i].y.y) - ny;
		bounds[i] = mp(l, r);
	}
	sort(ev, ev + ce);
	C(fen);
	rept(i, ce) {
		int v = ev[i].y.y;
		if (ev[i].y.x == 0) {
			upd(bounds[v].x, bounds[v].y, 1);
		} else
		if (ev[i].y.x == 1) {
			int y = lower_bound(ny, ny + k, met[v].y) - ny;
			if (sum(y)) return 1;
		} else {
			upd(bounds[v].x, bounds[v].y, -1);
		}
	}
	return 0;
}
bool check(int d) {
	if (ord[0].x <= d) return 1;
	if (ord[n - 1].x > d) return 0;
	int x1 = -INF, x2 = INF, y1 = -INF, y2 = INF;
	int cr = 0;
	rept(i, n) {
		int v = ord[i].y;
		if (ord[i].x <= d) {
			int left = d - ord[i].x;
			rect[cr++] = mp(mp(x1 - left, y1 - left), mp(x2 + left, y2 + left));
		}

		x1 = max(x1, gn[v].x - d);
		x2 = min(x2, gn[v].x + d);
		y1 = max(y1, gn[v].y - d);
		y2 = min(y2, gn[v].y + d);
	}
	if (!cr) return 0;
	if (inside(cr)) return 1; else
	return 0;
}
int solve_metro() {
	rept(i, n) ord[i] = mp(ds[i], i);
	sort(ord, ord + n); reverse(ord, ord + n);

	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check(xx)) r = xx; else
		l = xx;
	}
	return r;
}
int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	scanf("%d%d", &n, &m);
	rept(i, n) scanf("%d%d", &gn[i].x, &gn[i].y);
	rept(i, m) scanf("%d%d", &met[i].x, &met[i].y);

	if (m) findClosestMetro();

	rept(i, n) gn[i] = rot(gn[i]);
	rept(i, m) met[i] = rot(met[i]);
	int ans = simple();
	if (!m) {
		printf("%d\n", ans);
		exit(0);
	}

	ans = min(ans, solve_metro());
	printf("%d\n", ans);
}


#define _CRT_SECURE_NO_DEPRECATE
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <iterator>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
#include <cstring>
#pragma comment(linker, "/STACK:66777216")
using namespace std;
#define pb push_back
#define ppb pop_back
#define pi 3.1415926535897932384626433832795028841971
#define mp make_pair
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define INF 1000000000
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;i--)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,1,(n))
#define rept(i,n) FOR(i,0,(n)-1)
#define L(s) (int)((s).size())
#define C(a) memset((a),0,sizeof(a))
#define VI vector <int>
#define ll long long

template<int N> struct rmq {
	int tr[N * 2 + 2];
	int n;
	inline void reset() {
		memset(tr, 63, sizeof(tr));
	}
	inline void upd(int x, int val) {
		x += n;
		tr[x] = min(tr[x], val);
		for (; x /= 2; ) tr[x] = min(tr[x * 2], tr[x * 2 + 1]);
	}
	inline int fnd(int l, int r) {
		int ans = 2 * INF;
		for (l += n, r += n; l <= r; l = (l + 1) / 2, r = (r - 1) / 2) {
			if (l & 1) ans = min(ans, tr[l]);
			if (~r & 1) ans = min(ans, tr[r]);
		}
		return ans;
	}
};
int a,b,c,d,i,j,n,m,k,ans;
pii gn[100001], met[100001];
int ds[100001];

rmq<1 << 18> t1, t2;
int ny[300001];

inline bool cmp(const pair<pii, int> &a, const pair<pii, int> & b) {
	if (a.x.x != b.x.x) return a.x.x < b.x.x; else
	if (a.y != b.y) return a.y < b.y; else
	return a.x.y < b.x.y;
}
void solveMetro(vector<pair<pii, int> > &q) {
	sort(all(q), cmp);
	int k = 0;
	rept(i, L(q)) ny[k++] = q[i].x.y;
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	t1.n = k; t2.n = k;
	t1.reset(); t2.reset();
	rept(i, L(q)) {
		int cy = lower_bound(ny, ny + k, q[i].x.y) - ny;
		if (q[i].y == -1) {
			t1.upd(cy, -q[i].x.x - q[i].x.y);
			t2.upd(cy, -q[i].x.x + q[i].x.y);
		} else {
			int v1 = t1.fnd(0, cy) + q[i].x.x + q[i].x.y;
			int v2 = t2.fnd(cy, k - 1) + q[i].x.x - q[i].x.y;
			if (v1 < ds[q[i].y]) ds[q[i].y] = v1;
			if (v2 < ds[q[i].y]) ds[q[i].y] = v2;
		}
	}
}
void findClosestMetro() {
	memset(ds, 63, sizeof(ds));
	vector<pair<pii, int> > q;
	rept(i, n) {
		q.pb(mp(gn[i], i));
	}
	rept(i, m) {
		q.pb(mp(met[i], -1));
	}
	solveMetro(q);

	rept(i, L(q)) {
		q[i].x.x = -q[i].x.x;
		q[i].x.y = -q[i].x.y;
	}
	solveMetro(q);
}
inline pii rot(pii t) {
	return mp(t.x + t.y, t.x - t.y);
}

bool check_simple(int d) {
	int x1 = -INF, y1 = -INF, x2 = INF, y2 = INF;
	rept(i, n) {
		x1 = max(x1, gn[i].x - d);
		x2 = min(x2, gn[i].x + d);
		y1 = max(y1, gn[i].y - d);
		y2 = min(y2, gn[i].y + d);
	}
	if (x1 <= x2 && y1 <= y2) return 1; else
	return 0;
}
int simple() {
	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check_simple(xx)) r = xx; else
		l = xx;
	}
	return r;
}

pii ord[100001];
pair<pii, pii> rect[100001];
pair<int, pii> ev[300001];
pii bounds[100001];
int fen[300002];
int g;
inline void upd(int x, int val) {
	for (; x <= g; x |= x + 1) fen[x] += val;
}
inline void upd(int l, int r, int val) {
	upd(l, val);
	upd(r + 1, val - 1);
}
inline int sum(int x) {
	int ans = 0;
	for (; x >= 0; x = (x & (x + 1)) - 1) ans += fen[x];
	return ans;
}
bool inside(int cr) {
	int k = 0, ce = 0;
	rept(i, cr) {
		ny[k++] = rect[i].x.y;
		ny[k++] = rect[i].y.y;
		ev[ce++] = mp(rect[i].x.x, mp(0, i));
		ev[ce++] = mp(rect[i].y.x, mp(2, i));
	}
	rept(i, m) {
		ny[k++] = met[i].y;
		ev[ce++] = mp(met[i].x, mp(1, i));
	}
	sort(ny, ny + k);
	k = unique(ny, ny + k) - ny;
	g = k;
	rept(i, cr) {
		int l = lower_bound(ny, ny + k, rect[i].x.y) - ny;
		int r = lower_bound(ny, ny + k, rect[i].y.y) - ny;
		bounds[i] = mp(l, r);
	}
	sort(ev, ev + ce);
	C(fen);
	rept(i, ce) {
		int v = ev[i].y.y;
		if (ev[i].y.x == 0) {
			upd(bounds[v].x, bounds[v].y, 1);
		} else
		if (ev[i].y.x == 1) {
			int y = lower_bound(ny, ny + k, met[v].y) - ny;
			if (sum(y)) return 1;
		} else {
			upd(bounds[v].x, bounds[v].y, -1);
		}
	}
	return 0;
}
bool check(int d) {
	if (ord[0].x <= d) return 1;
	if (ord[n - 1].x > d) return 0;
	int x1 = -INF, x2 = INF, y1 = -INF, y2 = INF;
	int cr = 0;
	rept(i, n) {
		int v = ord[i].y;
		if (ord[i].x <= d) {
			int left = d - ord[i].x;
			rect[cr++] = mp(mp(x1 - left, y1 - left), mp(x2 + left, y2 + left));
		}

		x1 = max(x1, gn[v].x - d);
		x2 = min(x2, gn[v].x + d);
		y1 = max(y1, gn[v].y - d);
		y2 = min(y2, gn[v].y + d);
	}
	if (!cr) return 0;
	if (inside(cr)) return 1; else
	return 0;
}
int solve_metro() {
	rept(i, n) ord[i] = mp(ds[i], i);
	sort(ord, ord + n); reverse(ord, ord + n);

	int l = -1, r = INF;
	while (r - l > 1) {
		int xx = (r + l) / 2;
		if (check(xx)) r = xx; else
		l = xx;
	}
	return r;
}
int main() {
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	scanf("%d%d", &n, &m);
	rept(i, n) scanf("%d%d", &gn[i].x, &gn[i].y);
	rept(i, m) scanf("%d%d", &met[i].x, &met[i].y);

	if (m) findClosestMetro();

	rept(i, n) gn[i] = rot(gn[i]);
	rept(i, m) met[i] = rot(met[i]);
	int ans = simple();
	if (!m) {
		printf("%d\n", ans);
		exit(0);
	}

	ans = min(ans, solve_metro());
	printf("%d\n", ans);
}


#include<cstdio>
#include<algorithm>
#include<set>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,x,y) for(int i=(x);i>=(y);i--)
#define inf 200000002
#define mx 268435456
#define N 200000
#define M 2000000
using namespace std;
int n,m,k,ll,rr,mid,x1,y1,x2,y2,tot;bool u;
int a[M],L[M],R[M],l[M],r[M],L1[M],R1[M],l1[M],r1[M];
struct pr{int x,y,s;}t[N],p[N];set<int>se[M];
bool cmp(const pr &x,const pr &y){return x.x<y.x;}
bool cmp0(const pr &x,const pr &y){return x.s>y.s;}
void f(int x,int y,int z){if(z<a[x])a[x]=z;
	if(L[x]==y&&R[x]==y)return;
	if(y<=(L[x]+R[x])/2){
		if(!l[x]){
			l[x]=++tot;a[tot]=inf*2;l[tot]=r[tot]=0;
			L[tot]=L[x];R[tot]=(L[x]+R[x])/2;
		}f(l[x],y,z);
	}else{
		if(!r[x]){
			r[x]=++tot;a[tot]=inf*2;l[tot]=r[tot]=0;
			L[tot]=(L[x]+R[x])/2+1;R[tot]=R[x];
		}f(r[x],y,z);
	}
}
int q(int x,int l0,int r0){if(!x)return inf*4;
	if(L[x]==l0&&R[x]==r0)return a[x];
	if((L[x]+R[x])/2>=r0)return q(l[x],l0,r0);
	if((L[x]+R[x])/2<l0)return q(r[x],l0,r0);
	return min(q(l[x],l0,(L[x]+R[x])/2),
	q(r[x],(L[x]+R[x])/2+1,r0));
}
void nw(int l,int r){
	tot++;l1[tot]=r1[tot]=0;L1[tot]=l;R1[tot]=r;
}
void ins(int x,int y,int z){se[x].insert(z);
	if(L1[x]==y&&R1[x]==y)return;
	if(y<=(L1[x]+R1[x])/2){
		if(!l1[x]){
			l1[x]=++tot;l1[tot]=r1[tot]=0;
			L1[tot]=L1[x];R1[tot]=(L1[x]+R1[x])/2;
		}ins(l1[x],y,z);
	}else{
		if(!r1[x]){
			r1[x]=++tot;l1[tot]=r1[tot]=0;
			L1[tot]=(L1[x]+R1[x])/2+1;R1[tot]=R1[x];
		}ins(r1[x],y,z);
	}
}
bool qr(int x,int l0,int r0,int L0,int R0){if(!x)return 0;
	if(L1[x]==l0&&R1[x]==r0)return
		se[x].lower_bound(L0)!=se[x].upper_bound(R0);
	if((L1[x]+R1[x])/2>=r0)return qr(l1[x],l0,r0,L0,R0);
	if((L1[x]+R1[x])/2<l0)return qr(r1[x],l0,r0,L0,R0);
	return qr(l1[x],l0,(L1[x]+R1[x])/2,L0,R0)||
	qr(r1[x],(L1[x]+R1[x])/2+1,r0,L0,R0);
}
int main(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)scanf("%d%d",&t[i].x,&t[i].y);
	rep(i,1,m)scanf("%d%d",&p[i].x,&p[i].y);
	rep(i,1,n)t[i].x+=inf/2,t[i].y+=inf/2,t[i].s=inf*2;
	rep(i,1,m)p[i].x+=inf/2,p[i].y+=inf/2;
	sort(t+1,t+n+1,cmp);sort(p+1,p+m+1,cmp);
	l[1]=r[1]=0;k=tot=1;a[1]=inf*4;L[1]=1;R[1]=mx;
	rep(i,1,n){
		for(;k<=m&&p[k].x<=t[i].x;k++)f(1,p[k].y,-p[k].x-p[k].y);
		t[i].s=min(t[i].s,t[i].x+t[i].y+q(1,1,t[i].y));
	}
	l[1]=r[1]=0;k=tot=1;a[1]=inf*4;L[1]=1;R[1]=mx;
	rep(i,1,n){
		for(;k<=m&&p[k].x<=t[i].x;k++)f(1,p[k].y,-p[k].x+p[k].y);
		t[i].s=min(t[i].s,t[i].x-t[i].y+q(1,t[i].y,inf));
	}
	l[1]=r[1]=0;k=m;tot=1;a[1]=inf*4;L[1]=1;R[1]=mx;
	dep(i,n,1){
		for(;k>0&&p[k].x>=t[i].x;k--)f(1,p[k].y,p[k].x-p[k].y);
		t[i].s=min(t[i].s,-t[i].x+t[i].y+q(1,1,t[i].y));
	}
	l[1]=r[1]=0;k=m;tot=1;a[1]=inf*4;L[1]=1;R[1]=mx;
	dep(i,n,1){
		for(;k>0&&p[k].x>=t[i].x;k--)f(1,p[k].y,p[k].x+p[k].y);
		t[i].s=min(t[i].s,-t[i].x-t[i].y+q(1,t[i].y,inf));
	}
	tot=1;L1[1]=1;R1[1]=mx*2;
	sort(t+1,t+n+1,cmp0);ll=0;rr=inf*2;
	rep(i,1,m)ins(1,p[i].x-p[i].y+inf,p[i].x+p[i].y);
	for(mid=(ll+rr)/2;ll<rr;mid=(ll+rr)/2){
		x1=1;y1=1;x2=inf*2;y2=inf*2;u=0;
		rep(i,1,n){
			int X=t[i].x-t[i].y+inf,Y=t[i].x+t[i].y;
			if(X-mid>x1)x1=X-mid;if(Y-mid>y1)y1=Y-mid;
			if(X+mid<x2)x2=X+mid;if(Y+mid<y2)y2=Y+mid;
			if(x1>x2||y1>y2)break;
			if(t[i+1].s>mid)continue;
			if(i==n||qr(1,max(x1-mid+t[i+1].s,1),
			min(x2+mid-t[i+1].s,inf*2),
			max(y1-mid+t[i+1].s,1),
			min(y2+mid-t[i+1].s,inf*2))){u=1;break;}
		}
		if(u)rr=mid;else ll=mid+1;
	}
	printf("%d\n",mid);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <string>
#include <vector>

using namespace std;

#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define pb push_back
#define mp make_pair
#define sz(x) ((int)(x).size())

typedef long long ll;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef pair<int, int> pii;

const ll INFLL = 1e18;
class fenv_tree {
  vll xs;
  vector<pair<ll, int> > tr;
  static int f(int x) { return x ^ (x & (x - 1)); }

  public:
  fenv_tree(const vll &_xs) : xs(_xs), tr(sz(xs) + 1, mp(INFLL, -1)) {}
  void relax(ll x, const pair<ll, int> &val) {
    x = lower_bound(xs.begin(), xs.end(), x) - xs.begin();
    x++;
    assert(0 < x && x < sz(tr));
    for (; x > 0; x -= f(x))
      tr[x] = min(tr[x], val);
  }
  pair<ll, int> get(ll x) {
    x = lower_bound(xs.begin(), xs.end(), x) - xs.begin();
    x++;
    assert(0 <= x && x < sz(tr));
    pair<ll, int> res(INFLL, -1);
    for (; x < sz(tr); x += f(x))
      res = min(res, tr[x]);
    return res;
  }
};

struct pt {
  ll x, y;
  pt(ll _x = 0, ll _y = 0) : x(_x), y(_y) {}
  bool operator<(const pt &p2) const { return y != p2.y ? y < p2.y : x < p2.x; }
};

struct Ev {
  int ty;
  ll x, y;
  int  id;
  Ev(int _ty, ll _x, ll _y, int _id) : ty(_ty), x(_x), y(_y), id(_id) {}
  bool operator<(const Ev &e2) const {
    if (y != e2.y) return y > e2.y;
    if (x != e2.x) return x > e2.x;
    return ty > e2.ty;
  }
};

ll maxt;
void cross(ll &mix, ll &mxx, ll &miy, ll &mxy, const pt &p) {
  mix = max(mix, p.x - maxt);
  miy = max(miy, p.y - maxt);
  mxx = min(mxx, p.x + maxt);
  mxy = min(mxy, p.y + maxt);
}

vector<pt> subs;

bool findSubway(ll x1, ll x2, ll y1, ll y2) {
  for (int i = 0; i < sz(subs); i++)
    if (x1 <= subs[i].x && subs[i].x <= x2)
    if (y1 <= subs[i].y && subs[i].y <= y2)
      return true;
  return false;
}

int main() {
  #ifdef DEBUG
  freopen("std.in", "r", stdin);
  freopen("std.out", "w", stdout);
  #endif

  int n, m;
  while (scanf("%d%d", &n, &m) >= 1) {
    vector<pt> pts(n);
    subs.resize(m);
    sort(subs.begin(), subs.end());
    for (int i = 0; i < n; i++)
      scanf("%I64d%I64d", &pts[i].x, &pts[i].y);
    for (int i = 0; i < m; i++)
      scanf("%I64d%I64d", &subs[i].x, &subs[i].y);

    vi nearest(n, -1);
    vll ndist(n, INFLL);
    for (int step = 0; step < 4; step++) {
      vll xs;
      for (int i = 0; i < n; i++) xs.pb(pts[i].x);
      for (int i = 0; i < m; i++) xs.pb(subs[i].x);
      sort(xs.begin(), xs.end());
      xs.erase(unique(xs.begin(), xs.end()), xs.end());

      fenv_tree tr(xs);
      vector<Ev> evs;
      for (int i = 0; i < n; i++)
        evs.pb(Ev(0, pts[i].x, pts[i].y, i));
      for (int i = 0; i < m; i++)
        evs.pb(Ev(1, subs[i].x, subs[i].y, i));
      sort(evs.begin(), evs.end());

      for (int i = 0; i < sz(evs); i++) {
        if (evs[i].ty == 1) {
          tr.relax(evs[i].x, mp(evs[i].x + evs[i].y, evs[i].id));
        } else {
          pair<ll, int> cd = tr.get(evs[i].x);
          if (cd.second >= 0) {
            ll ncand = cd.first - evs[i].x - evs[i].y;
            if (ndist[evs[i].id] > ncand) {
              ndist[evs[i].id] = ncand;
              nearest[evs[i].id] = cd.second;
            }
          }
        }
      }

      if ((step & 1) == 0) {
        for (int i = 0; i < n; i++) pts[i].x = -pts[i].x;
        for (int i = 0; i < m; i++) subs[i].x = -subs[i].x;
      } else {
        for (int i = 0; i < n; i++) pts[i].y = -pts[i].y;
        for (int i = 0; i < m; i++) subs[i].y = -subs[i].y;
      }
    }

    #ifdef DEBUG
    for (int a = 0; a < n; a++) {
      ll bd = INFLL;
      for (int b = 0; b < m; b++)
        bd = min(bd, abs(pts[a].x - subs[b].x) + abs(pts[a].y - subs[b].y));
      assert(bd == ndist[a]);
      if (nearest[a] >= 0) {
        int b = nearest[a];
        assert(bd == abs(pts[a].x - subs[b].x) + abs(pts[a].y - subs[b].y));
      }
    }
    #endif

    vector<pair<ll, int> > ord(n);
    for (int i = 0; i < n; i++)
      ord[i] = mp(ndist[i], i);
    sort(ord.begin(), ord.end());

    for (int i = 0; i < n; i++) {
      pts[i] = pt(pts[i].x + pts[i].y, pts[i].x - pts[i].y);
    }
    for (int i = 0; i < m; i++) {
      subs[i] = pt(subs[i].x + subs[i].y, subs[i].x - subs[i].y);
    }

    ll L = -1, R = ord[n - 1].first;
    while (L + 1 < R) {
      maxt = (L + R) / 2;

      ll mix = -INFLL, miy = -INFLL;
      ll mxx = INFLL, mxy = INFLL;
      int ptr = n - 1;
      for (; ptr >= 0 && ord[ptr].first > maxt; ptr--) {
        cross(mix, mxx, miy, mxy, pts[ord[ptr].second]);
      }

      for (; ptr >= 0 && mix <= mxx && miy <= mxy; ptr--) {
        ll remt = maxt - ord[ptr].first;
        assert(remt >= 0);
        if (findSubway(mix - remt, mxx + remt, miy - remt, mxy + remt)) {
          break;
        } else {
          cross(mix, mxx, miy, mxy, pts[ord[ptr].second]);
        }
      }
      if (mix <= mxx && miy <= mxy) {
        R = maxt;
      } else
        L = maxt;
    }
    printf("%I64d\n", R);
  }
  return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <string>
#include <vector>

using namespace std;

#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define pb push_back
#define mp make_pair
#define sz(x) ((int)(x).size())

typedef long long ll;
typedef vector<ll> vll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef pair<int, int> pii;

const ll INFLL = 1e18;
class fenv_tree {
  vll xs;
  vector<pair<ll, int> > tr;
  static int f(int x) { return x ^ (x & (x - 1)); }

  public:
  fenv_tree(const vll &_xs) : xs(_xs), tr(sz(xs) + 1, mp(INFLL, -1)) {}
  void relax(ll x, const pair<ll, int> &val) {
    x = lower_bound(xs.begin(), xs.end(), x) - xs.begin();
    x++;
    assert(0 < x && x < sz(tr));
    for (; x > 0; x -= f(x))
      tr[x] = min(tr[x], val);
  }
  pair<ll, int> get(ll x) {
    x = lower_bound(xs.begin(), xs.end(), x) - xs.begin();
    x++;
    assert(0 <= x && x < sz(tr));
    pair<ll, int> res(INFLL, -1);
    for (; x < sz(tr); x += f(x))
      res = min(res, tr[x]);
    return res;
  }
};

struct pt {
  ll x, y;
  pt(ll _x = 0, ll _y = 0) : x(_x), y(_y) {}
  bool operator<(const pt &p2) const { return y != p2.y ? y < p2.y : x < p2.x; }
};

class segm_tree2 {
  vector<vll> tr;
  int off;
  vll ys;

  bool get(const vll &t, ll x1, ll x2) {
    int i = lower_bound(t.begin(), t.end(), x1) - t.begin();
    return i < sz(t) && t[i] <= x2;
  }

  public:
  segm_tree2() {}
  segm_tree2(const vector<pt> &pts) : ys(sz(pts)) {
    for (int i = 0; i < sz(pts); i++)
      ys[i] = pts[i].y;
    ys.erase(unique(ys.begin(), ys.end()), ys.end());

    off = 1; while (off <= sz(ys)) off <<= 1;
    tr = vector<vll>(2 * off);

    for (int i = 0; i < sz(pts); i++) {
      int v = lower_bound(ys.begin(), ys.end(), pts[i].y) - ys.begin();
      tr[off + v].pb(pts[i].x);
    }
    for (int i = off; i < sz(tr); i++) {
      sort(tr[i].begin(), tr[i].end());
      tr[i].erase(unique(tr[i].begin(), tr[i].end()), tr[i].end());
    }
    for (int i = off - 1; i >= 1; i--) {
      const vll &l = tr[2 * i], &r = tr[2 * i + 1];
      tr[i].resize(sz(l) + sz(r));
      merge(l.begin(), l.end(), r.begin(), r.end(), tr[i].begin());
      tr[i].erase(unique(tr[i].begin(), tr[i].end()), tr[i].end());
    }
  }
  bool get(ll x1, ll x2, ll y1, ll y2) {
    y1 = lower_bound(ys.begin(), ys.end(), y1) - ys.begin();
    y2 = upper_bound(ys.begin(), ys.end(), y2) - ys.begin() - 1;

    y1 += off; y2 += off;
    while (y1 <= y2) {
      if (y1 & 1) if (get(tr[y1++], x1, x2)) return true;
      if (!(y2 & 1)) if (get(tr[y2--], x1, x2)) return true;
      y1 >>= 1;
      y2 >>= 1;
    }
    return false;
  }
};

struct Ev {
  int ty;
  ll x, y;
  int  id;
  Ev(int _ty, ll _x, ll _y, int _id) : ty(_ty), x(_x), y(_y), id(_id) {}
  bool operator<(const Ev &e2) const {
    if (y != e2.y) return y > e2.y;
    if (x != e2.x) return x > e2.x;
    return ty > e2.ty;
  }
};

ll maxt;
void cross(ll &mix, ll &mxx, ll &miy, ll &mxy, const pt &p) {
  mix = max(mix, p.x - maxt);
  miy = max(miy, p.y - maxt);
  mxx = min(mxx, p.x + maxt);
  mxy = min(mxy, p.y + maxt);
}

vector<pt> subs;
segm_tree2 str;

#ifdef DEBUG
bool _findSubway(ll x1, ll x2, ll y1, ll y2) {
  for (int i = 0; i < sz(subs); i++)
    if (x1 <= subs[i].x && subs[i].x <= x2)
    if (y1 <= subs[i].y && subs[i].y <= y2)
      return true;
  return false;
}
#endif
bool findSubway(ll x1, ll x2, ll y1, ll y2)  {
//  eprintf("%d\n", _findSubway(x1, x2, y1, y2));
  #ifdef DEBUG
  assert(str.get(x1, x2, y1, y2) == _findSubway(x1, x2, y1, y2));
  #endif
  return str.get(x1, x2, y1, y2);
}

int main() {
  #ifdef DEBUG
  freopen("std.in", "r", stdin);
  freopen("std.out", "w", stdout);
  #endif

  int n, m;
  while (scanf("%d%d", &n, &m) >= 1) {
    vector<pt> pts(n);
    subs.resize(m);
    for (int i = 0; i < n; i++)
      scanf("%I64d%I64d", &pts[i].x, &pts[i].y);
    for (int i = 0; i < m; i++)
      scanf("%I64d%I64d", &subs[i].x, &subs[i].y);

    vi nearest(n, -1);
    vll ndist(n, INFLL);
    for (int step = 0; step < 4; step++) {
      vll xs;
      for (int i = 0; i < n; i++) xs.pb(pts[i].x);
      for (int i = 0; i < m; i++) xs.pb(subs[i].x);
      sort(xs.begin(), xs.end());
      xs.erase(unique(xs.begin(), xs.end()), xs.end());

      fenv_tree tr(xs);
      vector<Ev> evs;
      for (int i = 0; i < n; i++)
        evs.pb(Ev(0, pts[i].x, pts[i].y, i));
      for (int i = 0; i < m; i++)
        evs.pb(Ev(1, subs[i].x, subs[i].y, i));
      sort(evs.begin(), evs.end());

      for (int i = 0; i < sz(evs); i++) {
        if (evs[i].ty == 1) {
          tr.relax(evs[i].x, mp(evs[i].x + evs[i].y, evs[i].id));
        } else {
          pair<ll, int> cd = tr.get(evs[i].x);
          if (cd.second >= 0) {
            ll ncand = cd.first - evs[i].x - evs[i].y;
            if (ndist[evs[i].id] > ncand) {
              ndist[evs[i].id] = ncand;
              nearest[evs[i].id] = cd.second;
            }
          }
        }
      }

      if ((step & 1) == 0) {
        for (int i = 0; i < n; i++) pts[i].x = -pts[i].x;
        for (int i = 0; i < m; i++) subs[i].x = -subs[i].x;
      } else {
        for (int i = 0; i < n; i++) pts[i].y = -pts[i].y;
        for (int i = 0; i < m; i++) subs[i].y = -subs[i].y;
      }
    }

/*    #ifdef DEBUG
    for (int a = 0; a < n; a++) {
      ll bd = INFLL;
      for (int b = 0; b < m; b++)
        bd = min(bd, abs(pts[a].x - subs[b].x) + abs(pts[a].y - subs[b].y));
      assert(bd == ndist[a]);
      if (nearest[a] >= 0) {
        int b = nearest[a];
        assert(bd == abs(pts[a].x - subs[b].x) + abs(pts[a].y - subs[b].y));
      }
    }
    #endif*/

    vector<pair<ll, int> > ord(n);
    for (int i = 0; i < n; i++)
      ord[i] = mp(ndist[i], i);
    sort(ord.begin(), ord.end());

    for (int i = 0; i < n; i++) {
      pts[i] = pt(pts[i].x + pts[i].y, pts[i].x - pts[i].y);
    }
    for (int i = 0; i < m; i++) {
      subs[i] = pt(subs[i].x + subs[i].y, subs[i].x - subs[i].y);
    }
    sort(subs.begin(), subs.end());
    str = segm_tree2(subs);

    eprintf("go\n");
    ll L = -1, R = ord[n - 1].first;
    while (L + 1 < R) {
      maxt = (L + R) / 2;

      ll mix = -INFLL, miy = -INFLL;
      ll mxx = INFLL, mxy = INFLL;
      int ptr = n - 1;
      for (; ptr >= 0 && ord[ptr].first > maxt; ptr--) {
        cross(mix, mxx, miy, mxy, pts[ord[ptr].second]);
      }

      for (; ptr >= 0 && mix <= mxx && miy <= mxy; ptr--) {
        ll remt = maxt - ord[ptr].first;
        assert(remt >= 0);
        if (findSubway(mix - remt, mxx + remt, miy - remt, mxy + remt)) {
          break;
        } else {
          cross(mix, mxx, miy, mxy, pts[ord[ptr].second]);
        }
      }
      if (mix <= mxx && miy <= mxy) {
        R = maxt;
      } else
        L = maxt;
    }
    printf("%I64d\n", R);
  }
  return 0;
}


#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int limite=100001;
const int infinito=1000000000;

int n,m;

int xd[limite],yd[limite],xs[limite],ys[limite];
int h[limite][2][2];
int indice[limite];
int raiz;
int dd[limite];

void transforma(int &x,int &y)
{
  int nextx=2*(x-y);
  int nexty=2*(x+y);
  x=nextx;
  y=nexty;
}

void inserta(int u,int p)
{
  int dx=xs[u]<xs[p];
  int dy=ys[u]<ys[p];
  if (h[p][dx][dy]) inserta(u,h[p][dx][dy]);
  else h[p][dx][dy]=u;
}

int absolut(int x)
{
  if (x<0) return -x;
  return x;
}

int distancia(int x1,int y1,int x2,int y2)
{
  return max(absolut(x1-x2),absolut(y1-y2));
}

void cercano(int x,int y,int p,int &sol)
{
  if (p==0) return;
  sol=min(sol,distancia(x,y,xs[p],ys[p]));
  int dx=x<xs[p];
  int dy=y<ys[p];
  cercano(x,y,h[p][dx][dy],sol);
  if (x>=xs[p] and x-xs[p]<sol) cercano(x,y,h[p][1][dy],sol);
  if (x<xs[p] and xs[p]-x<sol) cercano(x,y,h[p][0][dy],sol);
  if (y>=ys[p] and y-ys[p]<sol) cercano(x,y,h[p][dx][1],sol);
  if (y<ys[p] and ys[p]-y<sol) cercano(x,y,h[p][dx][0],sol);
}

void cercano(int xinf,int yinf,int xsup,int ysup,int p,int &sol)
{
  if (p==0) return;
  sol=min(sol,distancia(xinf,yinf,xs[p],ys[p]));
  sol=min(sol,distancia(xsup,ysup,xs[p],ys[p]));
  if (xinf<=xs[p] and xs[p]<=xsup) sol=min(sol,absolut(ys[p]-ysup));
  if (yinf<=ys[p] and ys[p]<=ysup) sol=min(sol,absolut(xs[p]-xsup));
  {
    int dx=xinf<xs[p];
    int dy=yinf<ys[p];
    cercano(xinf,yinf,xsup,ysup,h[p][dx][dy],sol);
    if (xinf>=xs[p] and xinf-xs[p]<sol) cercano(xinf,yinf,xsup,ysup,h[p][1][dy],sol);
    if (yinf>=ys[p] and yinf-ys[p]<sol) cercano(xinf,yinf,xsup,ysup,h[p][dx][1],sol);
  }
  {
    int dx=xsup<xs[p];
    int dy=ysup<ys[p];
    cercano(xinf,yinf,xsup,ysup,h[p][dx][dy],sol);
    if (xsup<xs[p] and xs[p]-xsup<sol) cercano(xinf,yinf,xsup,ysup,h[p][0][dy],sol);
    if (ysup<ys[p] and ys[p]-ysup<sol) cercano(xinf,yinf,xsup,ysup,h[p][dx][0],sol);
  }
}

bool compara(int i1,int i2)
{
  return dd[i1]<dd[i2];
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  for (int i=0;i<n;i++) {
    cin>>xd[i]>>yd[i];
    transforma(xd[i],yd[i]);
  }
  for (int i=1;i<=m;i++) {
    cin>>xs[i]>>ys[i];
    transforma(xs[i],ys[i]);
    indice[i-1]=i;
  }
  random_shuffle(indice,indice+m);
  raiz=indice[0];
  for (int i=1;i<m;i++)
    inserta(indice[i],raiz);
  for (int i=0;i<n;i++) {
    dd[i]=infinito;
    cercano(xd[i],yd[i],raiz,dd[i]);
  }
  for (int i=0;i<n;i++)
    indice[i]=i;
  sort(indice,indice+n,compara);
  int sol=dd[indice[n-1]];
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=n-1;i>=0;i--) {
    int id=indice[i];
    xmax=max(xmax,xd[id]);
    xmin=min(xmin,xd[id]);
    ymax=max(ymax,yd[id]);
    ymin=min(ymin,yd[id]);
    if (m>0 and i>0) {
      int dist=distancia(xmin,ymin,xmax,ymax);
      int xinf=xmax-dist/2;
      int xsup=xmin+dist/2;
      int yinf=ymax-dist/2;
      int ysup=ymin+dist/2;
      int draya=infinito;
      cercano(xinf,yinf,xsup,ysup,raiz,draya);
      int tiempo=dd[indice[i-1]];
      if (tiempo+draya<=dist/2) sol=min(sol,dist/2);
      else if (draya+dist/2<=tiempo) sol=min(sol,tiempo);
      else sol=min(sol,(tiempo+draya+dist/2)/2);
    }
  }
  sol=min(sol,distancia(xmax,ymax,xmin,ymin)/2);
  cout<<(sol+1)/2<<endl;
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstdlib>

using namespace std;

int absolut(int x)
{
  if (x<0) return -x;
  return x;
}

int distancia(int x1,int y1,int x2,int y2)
{
  return max(absolut(x1-x2),absolut(y1-y2));
}

const int limite=100001;
const int infinito=2000000000;

struct elem {
  int id,x,y,x2;
  elem() {
  }
  elem(int inid,int inx,int iny) {
    id=inid;x=inx;y=iny;x2=1000;
  }
  elem(int inid,int inx,int iny,int inx2) {
    id=inid;x=inx;y=iny;x2=inx2;
  }
};

bool operator<(elem e1,elem e2) {
  return e1.y>e2.y or (e1.y==e2.y and e1.id<e2.id);
}

void limpiar(map<int,int> &mapa,int x)
{
  map<int,int>::iterator it=mapa.find(x);
  int y=it->second;
  for (;;) {
    map<int,int>::iterator it2=it;
    it2++;
    if (it2==mapa.end()) break;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
  for (;it!=mapa.begin();) {
    map<int,int>::iterator it2=it;
    it2--;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
}

void computadist(vector<elem> &ve,vector<int> &dist,int divi)
{
  sort(ve.begin(),ve.end());
  map<int,int> mapa;
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    int id=e.id;
    int x=e.x;
    int y=e.y;
    if (id==-1) {
      mapa[x]=y;
      limpiar(mapa,x);
    } else {
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.end()) dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
      }
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.begin()) {
	  it--;
	  dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
	}
      }
    }
  }
}

void computadistext(vector<elem> &ve,vector<int> &dist,int divi)
{
  computadist(ve,dist,divi);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computadist(ve,dist,divi);
}

const int tope=1<<20;
const int primero=1<<19;

int minimo[tope];

void inserta(int pos,int val)
{
  pos+=primero;
  minimo[pos]=val;
  while (pos>1) {
    pos/=2;
    minimo[pos]=min(minimo[2*pos],minimo[2*pos+1]);
  }
}

int minimoentre(int pos0,int pos1)
{
  pos0+=primero;
  pos1+=primero;
  if (pos0==pos1) return minimo[pos0];
  int mini=min(minimo[pos0],minimo[pos1]);
  while (pos0+1<pos1) {
    if (pos0%2==0) mini=min(mini,minimo[pos0+1]);
    pos0/=2;
    if (pos1%2==1) mini=min(mini,minimo[pos1-1]);
    pos1/=2;
  }
  return mini;
}

void computalinea(vector<elem> &ve,vector<int> &dist)
{
  for (int i=0;i<tope;i++)
    minimo[i]=infinito;
  map<int,int> posicion;
  for (int i=0;i<int(ve.size());i++) {
    posicion[ve[i].x];
    if (ve[i].id!=-1)
      posicion[ve[i].x2];
  }
  {
    int i=0;
    for (map<int,int>::iterator it=posicion.begin();it!=posicion.end();it++,i++)
      it->second=i;
  }
  sort(ve.begin(),ve.end());
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    if (e.id==-1) {
      inserta(posicion[e.x],e.y);
    } else {
      dist[e.id]=min(dist[e.id],minimoentre(posicion[e.x],posicion[e.x2])-e.y);
    }
  }
}

void computalineaext(vector<elem> &ve,vector<int> &dist)
{
  computalinea(ve,dist);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computalinea(ve,dist);
}

int n,m;

int xd[limite],yd[limite],xs[limite],ys[limite];
int indice[limite];
int dd[limite];

void transforma(int &x,int &y)
{
  int nextx=2*(x-y);
  int nexty=2*(x+y);
  x=nextx;
  y=nexty;
}

bool compara(int i1,int i2)
{
  return dd[i1]<dd[i2];
}

void versionfacil()
{
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=0;i<n;i++) {
    cin>>xd[i]>>yd[i];
    transforma(xd[i],yd[i]);
    xmax=max(xmax,xd[i]);
    xmin=min(xmin,xd[i]);
    ymax=max(ymax,yd[i]);
    ymin=min(ymin,yd[i]);
  }
  int sol=distancia(xmax,ymax,xmin,ymin)/2;
  cout<<(sol+1)/2<<endl;
  exit(0);
}

void escribe(vector<elem> &ve)
{
  for (int i=0;i<int(ve.size());i++)
    cout<<"("<<ve[i].id<<","<<ve[i].x<<","<<ve[i].y<<","<<ve[i].x2<<")";
  cout<<endl;
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  if (m==0) versionfacil();
  vector<elem> vesimple;
  vector<elem> vehor;
  vector<elem> vever;
  {
    vector<elem> ve;
    for (int i=0;i<n;i++) {
      cin>>xd[i]>>yd[i];
      ve.push_back(elem(i,xd[i],yd[i]));
      transforma(xd[i],yd[i]);
    }
    for (int i=0;i<m;i++) {
      cin>>xs[i]>>ys[i];
      ve.push_back(elem(-1,xs[i],ys[i]));
      vesimple.push_back(elem(-1,4*xs[i],4*ys[i]));
      transforma(xs[i],ys[i]);
      vehor.push_back(elem(-1,xs[i],ys[i]));
      vever.push_back(elem(-1,ys[i],xs[i]));
      indice[i]=i;
    }
    vector<int> dist(n,infinito);
    computadistext(ve,dist,1);
    for (int i=0;i<n;i++)
      dd[i]=dist[i];
    for (int i=0;i<n;i++)
      indice[i]=i;
    sort(indice,indice+n,compara);
  }
  /*
  for (int i=0;i<n;i++)
    cout<<dd[i]<<",";
  cout<<endl;
  */
  int sol=2*dd[indice[n-1]];
  {
    int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
    for (int i=n-1;i>=0;i--) {
      int id=indice[i];
      xmax=max(xmax,xd[id]);
      xmin=min(xmin,xd[id]);
      ymax=max(ymax,yd[id]);
      ymin=min(ymin,yd[id]);
      int dis=distancia(xmin,ymin,xmax,ymax);
      int xinf=xmax-dis/2;
      int xsup=xmin+dis/2;
      int yinf=ymax-dis/2;
      int ysup=ymin+dis/2;
      vesimple.push_back(elem(i,xinf+yinf,yinf-xinf));
      vesimple.push_back(elem(i,xsup+ysup,ysup-xsup));
      if (xinf!=xsup) vehor.push_back(elem(i,xinf,yinf,xsup));
      if (yinf!=ysup) vever.push_back(elem(i,yinf,xinf,ysup));
    }
    sol=min(sol,distancia(xmin,ymin,xmax,ymax)/2);
  }
  /*
  escribe(vesimple);
  escribe(vehor);
  escribe(vever);
  */
  vector<int> dist(n,infinito);
  computadistext(vesimple,dist,2);
  vector<int> disthor(n,infinito);
  computalineaext(vehor,disthor);
  vector<int> distver(n,infinito);
  computalineaext(vever,distver);
  /*
  for (int i=0;i<n;i++)
    cout<<dist[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<disthor[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<distver[i]<<",";
  cout<<endl;
  */
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=n-1;i>0;i--) {
    int id=indice[i];
    xmax=max(xmax,xd[id]);
    xmin=min(xmin,xd[id]);
    ymax=max(ymax,yd[id]);
    ymin=min(ymin,yd[id]);
    int dis=distancia(xmin,ymin,xmax,ymax);
    int draya=dist[i];
    int tiempo=dd[indice[i-1]];
    if (tiempo+draya<=dis/2) sol=min(sol,dis/2);
    else if (draya+dis/2<=tiempo) sol=min(sol,tiempo);
    else sol=min(sol,(tiempo+draya+dis/2)/2);
  }
  cout<<(sol+1)/2<<endl;
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstdlib>

using namespace std;

int absolut(int x)
{
  if (x<0) return -x;
  return x;
}

int distancia(int x1,int y1,int x2,int y2)
{
  return max(absolut(x1-x2),absolut(y1-y2));
}

const int limite=100001;
const int infinito=2000000000;

struct elem {
  int id,x,y,x2;
  elem() {
  }
  elem(int inid,int inx,int iny) {
    id=inid;x=inx;y=iny;x2=1000;
  }
  elem(int inid,int inx,int iny,int inx2) {
    id=inid;x=inx;y=iny;x2=inx2;
  }
};

bool operator<(elem e1,elem e2) {
  return e1.y>e2.y or (e1.y==e2.y and e1.id<e2.id);
}

void limpiar(map<int,int> &mapa,int x)
{
  map<int,int>::iterator it=mapa.find(x);
  int y=it->second;
  for (;;) {
    map<int,int>::iterator it2=it;
    it2++;
    if (it2==mapa.end()) break;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
  for (;it!=mapa.begin();) {
    map<int,int>::iterator it2=it;
    it2--;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
}

void computadist(vector<elem> &ve,vector<int> &dist,int divi)
{
  sort(ve.begin(),ve.end());
  map<int,int> mapa;
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    int id=e.id;
    int x=e.x;
    int y=e.y;
    if (id==-1) {
      mapa[x]=y;
      limpiar(mapa,x);
    } else {
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.end()) dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
      }
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.begin()) {
	  it--;
	  dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
	}
      }
    }
  }
}

void computadistext(vector<elem> &ve,vector<int> &dist,int divi)
{
  computadist(ve,dist,divi);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computadist(ve,dist,divi);
}

const int tope=1<<20;
const int primero=1<<19;

int minimo[tope];

void inserta(int pos,int val)
{
  pos+=primero;
  minimo[pos]=val;
  while (pos>1) {
    pos/=2;
    minimo[pos]=min(minimo[2*pos],minimo[2*pos+1]);
  }
}

int minimoentre(int pos0,int pos1)
{
  pos0+=primero;
  pos1+=primero;
  if (pos0==pos1) return minimo[pos0];
  int mini=min(minimo[pos0],minimo[pos1]);
  while (pos0+1<pos1) {
    if (pos0%2==0) mini=min(mini,minimo[pos0+1]);
    pos0/=2;
    if (pos1%2==1) mini=min(mini,minimo[pos1-1]);
    pos1/=2;
  }
  return mini;
}

void computalinea(vector<elem> &ve,vector<int> &dist)
{
  for (int i=0;i<tope;i++)
    minimo[i]=infinito;
  map<int,int> posicion;
  for (int i=0;i<int(ve.size());i++) {
    posicion[ve[i].x];
    if (ve[i].id!=-1)
      posicion[ve[i].x2];
  }
  {
    int i=0;
    for (map<int,int>::iterator it=posicion.begin();it!=posicion.end();it++,i++)
      it->second=i;
  }
  sort(ve.begin(),ve.end());
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    if (e.id==-1) {
      inserta(posicion[e.x],e.y);
    } else {
      dist[e.id]=min(dist[e.id],minimoentre(posicion[e.x],posicion[e.x2])-e.y);
    }
  }
}

void computalineaext(vector<elem> &ve,vector<int> &dist)
{
  computalinea(ve,dist);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computalinea(ve,dist);
}

int n,m;

int xd[limite],yd[limite],xs[limite],ys[limite];
int indice[limite];
int dd[limite];

void transforma(int &x,int &y)
{
  int nextx=2*(x-y);
  int nexty=2*(x+y);
  x=nextx;
  y=nexty;
}

bool compara(int i1,int i2)
{
  return dd[i1]<dd[i2];
}

void versionfacil()
{
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=0;i<n;i++) {
    cin>>xd[i]>>yd[i];
    transforma(xd[i],yd[i]);
    xmax=max(xmax,xd[i]);
    xmin=min(xmin,xd[i]);
    ymax=max(ymax,yd[i]);
    ymin=min(ymin,yd[i]);
  }
  int sol=distancia(xmax,ymax,xmin,ymin)/2;
  cout<<(sol+1)/2<<endl;
  exit(0);
}

void escribe(vector<elem> &ve)
{
  for (int i=0;i<int(ve.size());i++)
    cout<<"("<<ve[i].id<<","<<ve[i].x<<","<<ve[i].y<<","<<ve[i].x2<<")";
  cout<<endl;
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  if (m==0) versionfacil();
  vector<elem> vesimple;
  vector<elem> vehor;
  vector<elem> vever;
  {
    vector<elem> ve;
    for (int i=0;i<n;i++) {
      cin>>xd[i]>>yd[i];
      ve.push_back(elem(i,xd[i],yd[i]));
      transforma(xd[i],yd[i]);
    }
    for (int i=0;i<m;i++) {
      cin>>xs[i]>>ys[i];
      ve.push_back(elem(-1,xs[i],ys[i]));
      vesimple.push_back(elem(-1,4*xs[i],4*ys[i]));
      transforma(xs[i],ys[i]);
      vehor.push_back(elem(-1,xs[i],ys[i]));
      vever.push_back(elem(-1,ys[i],xs[i]));
      indice[i]=i;
    }
    vector<int> dist(n,infinito);
    computadistext(ve,dist,1);
    for (int i=0;i<n;i++)
      dd[i]=2*dist[i];
    for (int i=0;i<n;i++)
      indice[i]=i;
    sort(indice,indice+n,compara);
  }
  /*
  for (int i=0;i<n;i++)
    cout<<dd[i]<<",";
  cout<<endl;
  */
  int sol=dd[indice[n-1]];
  {
    int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
    for (int i=n-1;i>=0;i--) {
      int id=indice[i];
      xmax=max(xmax,xd[id]);
      xmin=min(xmin,xd[id]);
      ymax=max(ymax,yd[id]);
      ymin=min(ymin,yd[id]);
      int dis=distancia(xmin,ymin,xmax,ymax);
      int xinf=xmax-dis/2;
      int xsup=xmin+dis/2;
      int yinf=ymax-dis/2;
      int ysup=ymin+dis/2;
      vesimple.push_back(elem(i,xinf+yinf,yinf-xinf));
      vesimple.push_back(elem(i,xsup+ysup,ysup-xsup));
      if (xinf!=xsup) vehor.push_back(elem(i,xinf,yinf,xsup));
      if (yinf!=ysup) vever.push_back(elem(i,yinf,xinf,ysup));
    }
    sol=min(sol,distancia(xmin,ymin,xmax,ymax)/2);
  }
  /*
  cout<<sol<<endl;

  escribe(vesimple);
  escribe(vehor);
  escribe(vever);
  */
  vector<int> dist(n,infinito);
  computadistext(vesimple,dist,2);
  vector<int> disthor(n,infinito);
  computalineaext(vehor,dist);
  vector<int> distver(n,infinito);
  computalineaext(vever,dist);
  /*
  for (int i=0;i<n;i++)
    cout<<dist[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<disthor[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<distver[i]<<",";
  cout<<endl;
  */
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=n-1;i>0;i--) {
    int id=indice[i];
    xmax=max(xmax,xd[id]);
    xmin=min(xmin,xd[id]);
    ymax=max(ymax,yd[id]);
    ymin=min(ymin,yd[id]);
    int dis=distancia(xmin,ymin,xmax,ymax);
    int draya=dist[i];
    int tiempo=dd[indice[i-1]];
    if (tiempo+draya<=dis/2) sol=min(sol,dis/2);
    else if (draya+dis/2<=tiempo) sol=min(sol,tiempo);
    else sol=min(sol,(tiempo+draya+dis/2)/2);
  }
  cout<<(sol+1)/2<<endl;
}


#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstdlib>

using namespace std;

int absolut(int x)
{
  if (x<0) return -x;
  return x;
}

int distancia(int x1,int y1,int x2,int y2)
{
  return max(absolut(x1-x2),absolut(y1-y2));
}

const int limite=100001;
const int infinito=1000000000;

struct elem {
  int id,x,y,x2;
  elem() {
  }
  elem(int inid,int inx,int iny) {
    id=inid;x=inx;y=iny;x2=1000;
  }
  elem(int inid,int inx,int iny,int inx2) {
    id=inid;x=inx;y=iny;x2=inx2;
  }
};

bool operator<(elem e1,elem e2) {
  return e1.y>e2.y or (e1.y==e2.y and e1.id<e2.id);
}

void limpiar(map<int,int> &mapa,int x)
{
  map<int,int>::iterator it=mapa.find(x);
  int y=it->second;
  for (;;) {
    map<int,int>::iterator it2=it;
    it2++;
    if (it2==mapa.end()) break;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
  for (;it!=mapa.begin();) {
    map<int,int>::iterator it2=it;
    it2--;
    int x2=it2->first;
    int y2=it2->second;
    if (absolut(x2-x)<=absolut(y2-y)) mapa.erase(it2);
    else break;
  }
}

void computadist(vector<elem> &ve,vector<int> &dist,int divi)
{
  sort(ve.begin(),ve.end());
  map<int,int> mapa;
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    int id=e.id;
    int x=e.x;
    int y=e.y;
    if (id==-1) {
      mapa[x]=y;
      limpiar(mapa,x);
    } else {
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.end()) dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
      }
      {
	map<int,int>::iterator it=mapa.lower_bound(x);
	if (it!=mapa.begin()) {
	  it--;
	  dist[id]=min(dist[id],(absolut(x-it->first)+absolut(y-it->second))/divi);
	}
      }
    }
  }
}

void computadistext(vector<elem> &ve,vector<int> &dist,int divi)
{
  computadist(ve,dist,divi);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computadist(ve,dist,divi);
}

const int tope=1<<20;
const int primero=1<<19;

int minimo[tope];

void inserta(int pos,int val)
{
  pos+=primero;
  minimo[pos]=val;
  while (pos>1) {
    pos/=2;
    minimo[pos]=min(minimo[2*pos],minimo[2*pos+1]);
  }
}

int minimoentre(int pos0,int pos1)
{
  pos0+=primero;
  pos1+=primero;
  if (pos0==pos1) return minimo[pos0];
  int mini=min(minimo[pos0],minimo[pos1]);
  while (pos0+1<pos1) {
    if (pos0%2==0) mini=min(mini,minimo[pos0+1]);
    pos0/=2;
    if (pos1%2==1) mini=min(mini,minimo[pos1-1]);
    pos1/=2;
  }
  return mini;
}

void computalinea(vector<elem> &ve,vector<int> &dist)
{
  for (int i=0;i<tope;i++)
    minimo[i]=infinito;
  map<int,int> posicion;
  for (int i=0;i<int(ve.size());i++) {
    posicion[ve[i].x];
    if (ve[i].id!=-1)
      posicion[ve[i].x2];
  }
  {
    int i=0;
    for (map<int,int>::iterator it=posicion.begin();it!=posicion.end();it++,i++)
      it->second=i;
  }
  sort(ve.begin(),ve.end());
  for (int i=0;i<int(ve.size());i++) {
    elem &e=ve[i];
    if (e.id==-1) {
      inserta(posicion[e.x],e.y);
    } else {
      dist[e.id]=min(dist[e.id],minimoentre(posicion[e.x],posicion[e.x2])-e.y);
    }
  }
}

void computalineaext(vector<elem> &ve,vector<int> &dist)
{
  computalinea(ve,dist);
  for (int i=0;i<int(ve.size());i++)
    ve[i].y*=-1;
  computalinea(ve,dist);
}

int n,m;

int xd[limite],yd[limite],xs[limite],ys[limite];
int indice[limite];
int dd[limite];

void transforma(int &x,int &y)
{
  int nextx=2*(x-y);
  int nexty=2*(x+y);
  x=nextx;
  y=nexty;
}

bool compara(int i1,int i2)
{
  return dd[i1]<dd[i2];
}

void versionfacil()
{
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=0;i<n;i++) {
    cin>>xd[i]>>yd[i];
    transforma(xd[i],yd[i]);
    xmax=max(xmax,xd[i]);
    xmin=min(xmin,xd[i]);
    ymax=max(ymax,yd[i]);
    ymin=min(ymin,yd[i]);
  }
  int sol=distancia(xmax,ymax,xmin,ymin)/2;
  cout<<(sol+1)/2<<endl;
  exit(0);
}

void escribe(vector<elem> &ve)
{
  for (int i=0;i<int(ve.size());i++)
    cout<<"("<<ve[i].id<<","<<ve[i].x<<","<<ve[i].y<<","<<ve[i].x2<<")";
  cout<<endl;
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  if (m==0) versionfacil();
  vector<elem> vesimple;
  vector<elem> vehor;
  vector<elem> vever;
  {
    vector<elem> ve;
    for (int i=0;i<n;i++) {
      cin>>xd[i]>>yd[i];
      ve.push_back(elem(i,xd[i],yd[i]));
      transforma(xd[i],yd[i]);
    }
    for (int i=0;i<m;i++) {
      cin>>xs[i]>>ys[i];
      ve.push_back(elem(-1,xs[i],ys[i]));
      vesimple.push_back(elem(-1,4*xs[i],4*ys[i]));
      transforma(xs[i],ys[i]);
      vehor.push_back(elem(-1,xs[i],ys[i]));
      vever.push_back(elem(-1,ys[i],xs[i]));
      indice[i]=i;
    }
    vector<int> dist(n,infinito);
    computadistext(ve,dist,1);
    for (int i=0;i<n;i++)
      dd[i]=2*dist[i];
    for (int i=0;i<n;i++)
      indice[i]=i;
    sort(indice,indice+n,compara);
  }
  /*
  for (int i=0;i<n;i++)
    cout<<dd[i]<<",";
  cout<<endl;
  */
  int sol=dd[indice[n-1]];
  {
    int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
    for (int i=n-1;i>=0;i--) {
      int id=indice[i];
      xmax=max(xmax,xd[id]);
      xmin=min(xmin,xd[id]);
      ymax=max(ymax,yd[id]);
      ymin=min(ymin,yd[id]);
      int dis=distancia(xmin,ymin,xmax,ymax);
      int xinf=xmax-dis/2;
      int xsup=xmin+dis/2;
      int yinf=ymax-dis/2;
      int ysup=ymin+dis/2;
      vesimple.push_back(elem(i,xinf+yinf,yinf-xinf));
      vesimple.push_back(elem(i,xsup+ysup,ysup-xsup));
      if (xinf!=xsup) vehor.push_back(elem(i,xinf,yinf,xsup));
      if (yinf!=ysup) vever.push_back(elem(i,yinf,xinf,ysup));
    }
    sol=min(sol,distancia(xmin,ymin,xmax,ymax)/2);
  }
  /*
  cout<<sol<<endl;

  escribe(vesimple);
  escribe(vehor);
  escribe(vever);
  */
  vector<int> dist(n,infinito);
  computadistext(vesimple,dist,2);
  vector<int> disthor(n,infinito);
  computalineaext(vehor,dist);
  vector<int> distver(n,infinito);
  computalineaext(vever,dist);
  /*
  for (int i=0;i<n;i++)
    cout<<dist[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<disthor[i]<<",";
  cout<<endl;

  for (int i=0;i<n;i++)
    cout<<distver[i]<<",";
  cout<<endl;
  */
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=n-1;i>0;i--) {
    int id=indice[i];
    xmax=max(xmax,xd[id]);
    xmin=min(xmin,xd[id]);
    ymax=max(ymax,yd[id]);
    ymin=min(ymin,yd[id]);
    int dis=distancia(xmin,ymin,xmax,ymax);
    int draya=dist[i];
    int tiempo=dd[indice[i-1]];
    if (tiempo+draya<=dis/2) sol=min(sol,dis/2);
    else if (draya+dis/2<=tiempo) sol=min(sol,tiempo);
    else sol=min(sol,(tiempo+draya+dis/2)/2);
  }
  cout<<(sol+1)/2<<endl;
}


#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int limite=100001;
const int infinito=1000000000;

int n,m;

int xd[limite],yd[limite],xs[limite],ys[limite];
int h[limite][2][2];
int indice[limite];
int raiz;
int dd[limite];

void transforma(int &x,int &y)
{
  int nextx=2*(x-y);
  int nexty=2*(x+y);
  x=nextx;
  y=nexty;
}

void inserta(int u,int p)
{
  int dx=xs[u]<xs[p];
  int dy=ys[u]<ys[p];
  if (h[p][dx][dy]) inserta(u,h[p][dx][dy]);
  else h[p][dx][dy]=u;
}

int absolut(int x)
{
  if (x<0) return -x;
  return x;
}

int distancia(int x1,int y1,int x2,int y2)
{
  return max(absolut(x1-x2),absolut(y1-y2));
}

void cercano(int x,int y,int p,int &sol)
{
  if (p==0) return;
  sol=min(sol,distancia(x,y,xs[p],ys[p]));
  int dx=x<xs[p];
  int dy=y<ys[p];
  cercano(x,y,h[p][dx][dy],sol);
  if (x>=xs[p] and x-xs[p]<sol) cercano(x,y,h[p][1][dy],sol);
  if (x<xs[p] and xs[p]-x<sol) cercano(x,y,h[p][0][dy],sol);
  if (y>=ys[p] and y-ys[p]<sol) cercano(x,y,h[p][dx][1],sol);
  if (y<ys[p] and ys[p]-y<sol) cercano(x,y,h[p][dx][0],sol);
}

void cercano(int xinf,int yinf,int xsup,int ysup,int p,int &sol)
{
  if (p==0) return;
  sol=min(sol,distancia(xinf,yinf,xs[p],ys[p]));
  sol=min(sol,distancia(xsup,ysup,xs[p],ys[p]));
  if (xinf<=xs[p] and xs[p]<=xsup) sol=min(sol,absolut(ys[p]-ysup));
  if (yinf<=ys[p] and ys[p]<=ysup) sol=min(sol,absolut(xs[p]-xsup));
  int dxant,dyant;
  {
    int dx=xinf<xs[p];
    int dy=yinf<ys[p];
    dxant=dx;dyant=dy;
    cercano(xinf,yinf,xsup,ysup,h[p][dx][dy],sol);
    if (xinf>=xs[p] and xinf-xs[p]<sol) cercano(xinf,yinf,xsup,ysup,h[p][1][dy],sol);
    if (yinf>=ys[p] and yinf-ys[p]<sol) cercano(xinf,yinf,xsup,ysup,h[p][dx][1],sol);
  }
  {
    int dx=xsup<xs[p];
    int dy=ysup<ys[p];
    if (dxant!=dx or dyant!=dy)
      cercano(xinf,yinf,xsup,ysup,h[p][dx][dy],sol);
    if (xsup<xs[p] and xs[p]-xsup<sol) cercano(xinf,yinf,xsup,ysup,h[p][0][dy],sol);
    if (ysup<ys[p] and ys[p]-ysup<sol) cercano(xinf,yinf,xsup,ysup,h[p][dx][0],sol);
  }
}

bool compara(int i1,int i2)
{
  return dd[i1]<dd[i2];
}

int main()
{
  ios::sync_with_stdio(false);
  cin>>n>>m;
  for (int i=0;i<n;i++) {
    cin>>xd[i]>>yd[i];
    transforma(xd[i],yd[i]);
  }
  for (int i=1;i<=m;i++) {
    cin>>xs[i]>>ys[i];
    transforma(xs[i],ys[i]);
    indice[i-1]=i;
  }
  random_shuffle(indice,indice+m);
  raiz=indice[0];
  for (int i=1;i<m;i++)
    inserta(indice[i],raiz);
  for (int i=0;i<n;i++) {
    dd[i]=infinito;
    cercano(xd[i],yd[i],raiz,dd[i]);
  }
  for (int i=0;i<n;i++)
    indice[i]=i;
  sort(indice,indice+n,compara);
  int sol=dd[indice[n-1]];
  int xmax=-infinito,xmin=infinito,ymax=-infinito,ymin=infinito;
  for (int i=n-1;i>=0;i--) {
    int id=indice[i];
    xmax=max(xmax,xd[id]);
    xmin=min(xmin,xd[id]);
    ymax=max(ymax,yd[id]);
    ymin=min(ymin,yd[id]);
    if (m>0 and i>0) {
      int dist=distancia(xmin,ymin,xmax,ymax);
      int xinf=xmax-dist/2;
      int xsup=xmin+dist/2;
      int yinf=ymax-dist/2;
      int ysup=ymin+dist/2;
      int draya=infinito;
      cercano(xinf,yinf,xsup,ysup,raiz,draya);
      int tiempo=dd[indice[i-1]];
      if (tiempo+draya<=dist/2) sol=min(sol,dist/2);
      else if (draya+dist/2<=tiempo) sol=min(sol,tiempo);
      else sol=min(sol,(tiempo+draya+dist/2)/2);
    }
  }
  sol=min(sol,distancia(xmax,ymax,xmin,ymin)/2);
  cout<<(sol+1)/2<<endl;
}


#include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<cstring>
using namespace std;

#define FOR(I,A,B) for (int I=int(A);I<int(B);++I)
#define MEM(A,B) memset(A,B,sizeof(A))
#define CPY(A,B) memcpy(A,B,sizeof(B))
#define FIN(A) freopen(A, "r", stdin)
#define FOUT(A) freopen(A, "w", stdout)
typedef long long LL;
const int N(150010), INF((1 << 30) - 1);
int ty, n, k;
int yy[4 * N], c1[4 * N], c2[4 * N];
int ord[N], dis[N], ans[N];
struct Point {
    int x, y;
    Point() : x(0), y(0) {}
    Point(int _x, int _y) : x(_x), y(_y) {}
    void get() {
	 scanf("%d%d",&x, &y);
    }
    void changeIndex() {
	 int _x(x), _y(y);
	 x = _x + _y;
	 y = _x - _y;
    }
    void rotate() {
	 swap(x, y); y = -y;
    }
    void getIndex() {
	 y = lower_bound(yy + 1, yy + 1 + ty, y) - yy;
    }
    void reflect() {
         yy[++ty] = y;
    }
}p1[N], p2[N], sub[N], dwa[N];
struct Line {
    int x, l, r, id;
    Line() : x(0), l(0), r(0), id(0) {}
    Line(int _x, int _l, int _r, int _id) {
	x = _x; l = _l; r = _r; id = _id;
    }
    void reflect() {
	 yy[++ty] = l;
	 yy[++ty] = r;
    }
    void getIndex() {
	 l = lower_bound(yy + 1, yy + 1 + ty, l) - yy;
	 r = lower_bound(yy + 1, yy + 1 + ty, r) - yy;
    }
}li[2 * N];
void numberY() {
     sort(yy + 1, yy + 1 + ty);
     int tt = 0;
     FOR(i, 1, ty + 1)
        if (i == 1 || yy[i] != yy[i - 1]) yy[++tt] = yy[i];
     ty = tt;
}
int low(int x) {return x & (-x);}
void update1(int x, int v) {
     for (; x <= ty; x += low(x)) c1[x] = min(c1[x], v);
}
int getValue1(int x) {
    int ret = INF;
    for (; x; x -= low(x)) ret = min(ret, c1[x]);
    return ret;
}
void update2(int x) {
     for (; x <= ty; x += low(x)) ++c2[x];
}
int getValue2(int x) {
    int ret = 0;
    for (; x; x -= low(x)) ret += c2[x];
    return ret;
}
bool cmpOrder1(int a, int b) {return p2[a].x < p2[b].x;}
bool cmpOrder2(int a, int b) {return dis[a] < dis[b];}
bool cmpPoint(Point a, Point b) {return a.x < b.x;}
bool cmpLine(Line a, Line b) {return a.x < b.x;}
void getMinDistance() {
     FOR(i, 0, n) dis[i] = INF;
     FOR(cal_time, 0, 4) {
        ty = 0;
	FOR(i, 0, k) {
	   sub[i].rotate();
	   sub[i].reflect();
	   p1[i] = sub[i];
	}
	FOR(i, 0, n) {
	   dwa[i].rotate();
	   dwa[i].reflect();
	   p2[i] = dwa[i];
	}
	numberY();
	FOR(i, 0, k)
	   p1[i].getIndex();
	FOR(i, 0, n) {
	   p2[i].getIndex();
	   ord[i] = i;
	}
	sort(p1, p1 + k, cmpPoint);
	sort(ord, ord + n, cmpOrder1);
	int p = 0;
	FOR(i, 0, ty + 1) c1[i] = INF;
	FOR(i, 0, n) {
	   for (; p < k && p1[p].x <= p2[ord[i]].x; ++p)
	       update1(p1[p].y, - p1[p].x - yy[p1[p].y]);
	   dis[ord[i]] = min(dis[ord[i]], p2[ord[i]].x + yy[p2[ord[i]].y] + getValue1(p2[ord[i]].y));
	}
     }
}
bool check(int v) {
     int x1 = -INF, y1 = -INF, x2 = INF, y2 = INF, e = 0;
     for (int i = n - 1; i != -1; --i) {
	 x1 = max(x1, dwa[ord[i]].x - v);
	 x2 = min(x2, dwa[ord[i]].x + v);
	 y1 = max(y1, dwa[ord[i]].y - v);
	 y2 = min(y2, dwa[ord[i]].y + v);
	 if (i && dis[ord[i - 1]] > v) continue;
	 int d = i ? v - dis[ord[i - 1]] : 0;
	 if (x1 > x2 || y1 > y2) break;
	 li[e++] = Line(x1 - d - 1, y1 - d - 1, y2 + d, - i - 1);
	 li[e++] = Line(x2 + d, y1 - d - 1, y2 + d, i + 1);
     }
     if (x1 <= x2 && y1 <= y2) return true;
     ty = 0;
     FOR(i, 0, e)
        li[i].reflect();
     FOR(i, 0, k) {
        p1[i] = sub[i];
        p1[i].reflect();
     }
     numberY();
     FOR(i, 0, e)
        li[i].getIndex();
     FOR(i, 0, k)
        p1[i].getIndex();
     sort(li, li + e, cmpLine);
     int p = 0;
     MEM(c2, 0);
     MEM(ans, 0);
     FOR(i, 0, e) {
	for (; p < k && p1[p].x <= li[i].x; ++p)
	    update2(p1[p].y);
	int t = li[i].id > 0 ? 1 : -1;
	ans[t * li[i].id] += t * (getValue2(li[i].r) - getValue2(li[i].l));
	if (ans[t * li[i].id] > 0) return true;
     }
     return false;
}
int main() {
    //FIN("in.txt");
    cin >> n >> k;
    FOR(i, 0, n)
       dwa[i].get();
    FOR(i, 0, k)
       sub[i].get();
    getMinDistance();
    FOR(i, 0, n)
       dwa[i].changeIndex();
    FOR(i, 0, k)
       sub[i].changeIndex();
    int l = 0, r = INF;
    sort(sub, sub + k, cmpPoint);
    sort(ord, ord + n, cmpOrder2);
    while (l != r) {
	  int mid = (l + r) / 2;
	  if (check(mid)) r = mid;
	  else l = mid + 1;
    }
    cout << l << endl;
    return 0;
}


#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>

using namespace std;

#define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)

typedef long long ll;

ll power(ll x, ll n, ll p){
    if(n == 0) return 1;
    ll y = power(x, n/2, p);
    y = y * y % p;
    if(n % 2 == 1) y = y * x % p;
    return y;
}

ll power2(ll x, ll n, ll p){ // (x ^ (2 ^ n)) mod p
    if(x % p == 0) return 0;
    ll tmp = power(2, n, p-1);
    return power(x, tmp, p);
}

ll func(ll x, ll l, ll r, ll p){
    int i;

    if(p == 2){
        if(x%2 == 0) return 1;
        return 0;
    }

    ll y = power2(x, l, p);

    ll z;
    if(y == 1){
        z = power(2, r+1-l, p);
    } else {
        ll a = power2(x, r+1, p);
        a = (a + p - 1) % p;
        ll b = y;
        b = (b + p - 1) % p;
        z = a * power(b, p-2, p) % p;
    }

    if(x % 2 == 0) return z;

    ll ord_sum = r - l + 1;
    ll max_ord = 1;

    if(l == 0){
        ll tmp = x + 1;
        max_ord = 0;
        while(tmp % 2 == 0){
            tmp /= 2;
            max_ord++;
        }
        ord_sum += max_ord - 1;
    }

    ord_sum -= max_ord;
    ll two = power(2, ord_sum, p);
    z = z * power(two, p-2, p) % p;

    return z;
}

int main(void){
    int T,t;
    ll x,l,r,p;

    cin >> T;
    REP(t,T){
        cin >> x >> l >> r >> p;
        ll ans = func(x, l, r, p);
        cout << ans << endl;
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5, inf = 1e9 + 1000;

int n, m, x, y, ans1;
pair < int, int > a[N], b[N], c[N];

struct item{
    item *l, *r;
    set < int > q;
    item(){
        l = r = nullptr;
    }
};
typedef item *pitem;

pitem root = nullptr;

void update(pitem v, int l, int r, int pos, int val){
    v->q.insert(val);
    if(l == r){
        return;
    }
    int mid = (r + l) >> 1;
    if(pos <= mid){
        if(!v->l){
            v->l = new item();
        }
        update(v->l, l, mid, pos, val);
    }
    else{
        if(!v->r){
            v->r = new item();
        }
        update(v->r, mid + 1, r, pos, val);
    }
}

bool exist(pitem v, int l, int r, int tl, int tr, int x, int y){
    if(!v || l > r || l > tr || tl > r || *v->q.begin() > y || *v->q.rbegin() < x){
        return false;
    }
    if(tl <= l && r <= tr){
        auto it = v->q.lower_bound(x);
        if(it != v->q.end() && *it <= y){
            return true;
        }
        return false;
    }
    int mid = (r + l) >> 1;
    bool yy = exist(v->l, l, mid, tl, tr, x, y);
    return yy ? true : exist(v->r, mid + 1, r, tl, tr, x, y);
}

inline bool check(int x){
    int mnx = INT_MAX, mxx = INT_MIN, mny = INT_MAX, mxy = INT_MIN;
    for(int i = n; i >= 1; i--){
        int j = c[i].second;
        mnx = max(mnx, a[j].first - x);
        mxx = min(mxx, a[j].first + x);
        mny = max(mny, a[j].second - x);
        mxy = min(mxy, a[j].second + x);
        if(mnx > mxx || mny > mxy){
            return false;
        }
        if(i == 1){
            return true;
        }
        if(c[i - 1].first <= x){
            int left = x - c[i - 1].first;
            if(exist(root, -inf, inf, mnx - left, mxx + left, mny - left, mxy + left)){
                return true;
            }
        }
    }
    assert(false);
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> x >> y;
        a[i] = make_pair(x + y, x - y);
    }
    for(int i = 1; i <= m; i++){
        cin >> x >> y;
        b[i] = make_pair(x + y, x - y);
    }
    int mnx = a[1].first, mxx = a[1].first, mny = a[1].second, mxy = a[1].second;
    for(int i = 2; i <= n; i++){
        mnx = min(mnx, a[i].first);
        mxx = max(mxx, a[i].first);
        mny = min(mny, a[i].second);
        mxy = max(mxy, a[i].second);
    }
    ans1 = max((mxx - mnx + 1) / 2, (mxy - mny + 1) / 2);
    if(m == 0){
        return cout << ans1, 0;
    }
    root = new item();
    for(int i = 1; i <= m; i++){
        update(root, -inf, inf, b[i].first, b[i].second);
    }
    for(int i = 1; i <= n; i++){
        int l = 0, r = 4e8;
        while(r - l > 1){
            int mid = (r + l) >> 1;
            if(exist(root, -inf, inf, a[i].first - mid, a[i].first + mid, a[i].second - mid, a[i].second + mid)){
                r = mid;
            }
            else{
                l = mid;
            }
        }
        if(exist(root, -inf, inf, a[i].first - l, a[i].first + l, a[i].second - l, a[i].second + l)){
            c[i].first = l;
        }
        else{
            c[i].first = r;
        }
    }
    sort(c + 1, c + n + 1);
    int l = 0, r = ans1 + 1;
    while(r - l > 1){
        int mid = (r + l) >> 1;
        if(check(mid)){
            r = mid;
        }
        else{
            l = mid;
        }
    }
    int ans2;
    if(check(l)){
        ans2 = l;
    }
    else{
        ans2 = r;
    }
    cout << min(ans1, ans2);
}


#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5, inf = 1e9 + 1000;

int n, m, x, y, ans1;
pair < int, int > a[N], b[N], c[N];

struct item{
    item *l, *r;
    set < int > q;
    item(){
        l = r = nullptr;
    }
};
typedef item *pitem;

pitem root = nullptr;

void update(pitem v, int l, int r, int pos, int val){
    v->q.insert(val);
    if(l == r){
        return;
    }
    int mid = (r + l) >> 1;
    if(pos <= mid){
        if(!v->l){
            v->l = new item();
        }
        update(v->l, l, mid, pos, val);
    }
    else{
        if(!v->r){
            v->r = new item();
        }
        update(v->r, mid + 1, r, pos, val);
    }
}

bool exist(pitem v, int l, int r, int tl, int tr, int x, int y){
    if(!v || l > r || l > tr || tl > r){
        return false;
    }
    if(tl <= l && r <= tr){
        auto it = v->q.lower_bound(x);
        if(it != v->q.end() && *it <= y){
            return true;
        }
        return false;
    }
    int mid = (r + l) >> 1;
    bool yy = exist(v->l, l, mid, tl, tr, x, y);
    return yy ? true : exist(v->r, mid + 1, r, tl, tr, x, y);
}

inline bool check(int x){
    int mnx = INT_MAX, mxx = INT_MIN, mny = INT_MAX, mxy = INT_MIN;
    for(int i = n; i >= 1; i--){
        int j = c[i].second;
        mnx = max(mnx, a[j].first - x);
        mxx = min(mxx, a[j].first + x);
        mny = max(mny, a[j].second - x);
        mxy = min(mxy, a[j].second + x);
        if(mnx > mxx || mny > mxy){
            return false;
        }
        if(i == 1){
            return true;
        }
        if(c[i - 1].first <= x){
            int left = x - c[i - 1].first;
            if(exist(root, -inf, inf, mnx - left, mxx + left, mny - left, mxy + left)){
                return true;
            }
        }
    }
    assert(false);
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> x >> y;
        a[i] = make_pair(x + y, x - y);
    }
    for(int i = 1; i <= m; i++){
        cin >> x >> y;
        b[i] = make_pair(x + y, x - y);
    }
    int mnx = a[1].first, mxx = a[1].first, mny = a[1].second, mxy = a[1].second;
    for(int i = 2; i <= n; i++){
        mnx = min(mnx, a[i].first);
        mxx = max(mxx, a[i].first);
        mny = min(mny, a[i].second);
        mxy = max(mxy, a[i].second);
    }
    ans1 = max((mxx - mnx + 1) / 2, (mxy - mny + 1) / 2);
    if(m == 0){
        return cout << ans1, 0;
    }
    root = new item();
    for(int i = 1; i <= m; i++){
        update(root, -inf, inf, b[i].first, b[i].second);
    }
    for(int i = 1; i <= n; i++){
        int l = 0, r = 4e8;
        while(r - l > 1){
            int mid = (r + l) >> 1;
            if(exist(root, -inf, inf, a[i].first - mid, a[i].first + mid, a[i].second - mid, a[i].second + mid)){
                r = mid;
            }
            else{
                l = mid;
            }
        }
        if(exist(root, -inf, inf, a[i].first - l, a[i].first + l, a[i].second - l, a[i].second + l)){
            c[i].first = l;
        }
        else{
            c[i].first = r;
        }
        c[i].second = i;
    }
    sort(c + 1, c + n + 1);
    int l = 0, r = c[n].first;
    while(r - l > 1){
        int mid = (r + l) >> 1;
        if(check(mid)){
            r = mid;
        }
        else{
            l = mid;
        }
    }
    int ans2;
    if(check(l)){
        ans2 = l;
    }
    else{
        ans2 = r;
    }
    //cout << ans1 << " " << ans2 << "\n";
    cout << min(ans1, ans2);
}


#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5, inf = 1e9 + 1000;

int n, m, x, y, ans1;
pair < int, int > a[N], b[N], c[N];

struct item{
    item *l, *r;
    set < int > q;
    item(){
        l = r = nullptr;
    }
};
typedef item *pitem;

pitem root = nullptr;

void update(pitem v, int l, int r, int pos, int val){
    v->q.insert(val);
    if(l == r){
        return;
    }
    int mid = (r + l) >> 1;
    if(pos <= mid){
        if(!v->l){
            v->l = new item();
        }
        update(v->l, l, mid, pos, val);
    }
    else{
        if(!v->r){
            v->r = new item();
        }
        update(v->r, mid + 1, r, pos, val);
    }
}

bool exist(pitem v, int l, int r, int tl, int tr, int x, int y){
    if(!v || l > r || l > tr || tl > r){
        return false;
    }
    if(tl <= l && r <= tr){
        auto it = v->q.lower_bound(x);
        if(it != v->q.end() && *it <= y){
            return true;
        }
        return false;
    }
    int mid = (r + l) >> 1;
    bool yy = exist(v->l, l, mid, tl, tr, x, y);
    return yy ? true : exist(v->r, mid + 1, r, tl, tr, x, y);
}

inline bool check(int x){
    int mnx = -INT_MAX, mxx = INT_MAX, mny = -INT_MAX, mxy = INT_MAX;
    for(int i = n; i >= 1; i--){
        int j = c[i].second;
        mnx = max(mnx, a[j].first - x);
        mxx = min(mxx, a[j].first + x);
        mny = max(mny, a[j].second - x);
        mxy = min(mxy, a[j].second + x);
        //cout << j << " " << mnx << " " << mxx << " " << mny << " " << mxy << "\n";
        if(mnx > mxx || mny > mxy){
            return false;
        }
        if(i == 1){
            return true;
        }
        if(c[i - 1].first <= x){
            int left = x - c[i - 1].first;
            if(exist(root, -inf, inf, mnx - left, mxx + left, mny - left, mxy + left)){
                return true;
            }
        }
    }
    assert(false);
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> x >> y;
        a[i] = make_pair(x + y, x - y);
    }
    for(int i = 1; i <= m; i++){
        cin >> x >> y;
        b[i] = make_pair(x + y, x - y);
    }
    int mnx = a[1].first, mxx = a[1].first, mny = a[1].second, mxy = a[1].second;
    for(int i = 2; i <= n; i++){
        mnx = min(mnx, a[i].first);
        mxx = max(mxx, a[i].first);
        mny = min(mny, a[i].second);
        mxy = max(mxy, a[i].second);
    }
    ans1 = max((mxx - mnx + 1) / 2, (mxy - mny + 1) / 2);
    if(m == 0){
        return cout << ans1, 0;
    }
    root = new item();
    for(int i = 1; i <= m; i++){
        update(root, -inf, inf, b[i].first, b[i].second);
    }
    for(int i = 1; i <= n; i++){
        int l = 0, r = 4e8;
        while(r - l > 1){
            int mid = (r + l) >> 1;
            if(exist(root, -inf, inf, a[i].first - mid, a[i].first + mid, a[i].second - mid, a[i].second + mid)){
                r = mid;
            }
            else{
                l = mid;
            }
        }
        if(exist(root, -inf, inf, a[i].first - l, a[i].first + l, a[i].second - l, a[i].second + l)){
            c[i].first = l;
        }
        else{
            c[i].first = r;
        }
        c[i].second = i;
    }
    sort(c + 1, c + n + 1);
    int l = 0, r = c[n].first;
    while(r - l > 1){
        int mid = (r + l) >> 1;
        if(check(mid)){
            r = mid;
        }
        else{
            l = mid;
        }
    }
    int ans2;
    if(check(l)){
        ans2 = l;
    }
    else{
        ans2 = r;
    }
    //cout << ans1 << " " << ans2 << "\n";
    cout << min(ans1, ans2);
}


#include <bits/stdc++.h>
using namespace std;
const int N = 200005,INF = 200000000;
int n,kk;pair<int,int> s[N];struct Node {int x,y,t;} a[N];
inline int lowbit(int x) {return x & -x;}
struct BIT
{
	int sz,c[N];BIT() {memset(c,191,sizeof(c));}
	void add(int x,int v)
	{ while (x <= sz) c[x] = max(c[x],v),x += lowbit(x); }
	int query(int x)
	{
		int ret = c[0];while (x) { ret = max(ret,c[x]);x -= lowbit(x); }
		return ret;
	}
};
struct TNode {int lc,rc,v;} t[N << 5];int idx;
void modify(int &pos,int l,int r,int v)
{
	int tt = ++idx;t[tt] = t[pos];pos = tt;++t[tt].v;
	int mid = (l + r) >> 1;
	if (l == r) return;
	if (v <= mid) modify(t[pos].lc,l,mid,v);
	else modify(t[pos].rc,mid + 1,r,v);
}
int query(int pos,int l,int r,int ql,int qr)
{
	if (!t[pos].v || (ql <= l && r <= qr)) return t[pos].v;
	int mid = (l + r) >> 1;
	if (qr <= mid) return query(t[pos].lc,l,mid,ql,qr);
	else if (ql > mid) return query(t[pos].rc,mid + 1,r,ql,qr);
	return query(t[pos].lc,l,mid,ql,qr) + query(t[pos].rc,mid + 1,r,ql,qr);
}
int rt[N];
int qrect(int x1,int x2,int y1,int y2)
{
	if (y2 < -INF || y1 > INF) return 0;
	int pl = lower_bound(s + 1,s + kk + 1,pair<int,int>{x1,-INF}) - s - 1,
	pr = lower_bound(s + 1,s + kk + 1,pair<int,int>{x2 + 1,-INF}) - s - 1;
	return query(rt[pr],-INF,INF,y1,y2) - query(rt[pl],-INF,INF,y1,y2);
}
int main ()
{
	ios::sync_with_stdio(false);
	cin >> n >> kk;
	for (int i = 1;i <= n;i++)
		cin >> a[i].x >> a[i].y,a[i].t = INF;
	for (int i = 1;i <= kk;i++) cin >> s[i].first >> s[i].second;
	vector<Node> pp;for (int i = 1;i <= n;i++) pp.push_back(a[i]);
	for (int i = 1;i <= kk;i++) pp.push_back({s[i].first,s[i].second,-1});
	for (int i = 0;i < 4;i++)
	{
		sort(pp.begin(),pp.end(),[](Node a,Node b) {return a.x < b.x || (a.x == b.x
			&& (a.y < b.y || (a.y == b.y && a.t < b.t)));});
		vector<int> vv;vv.push_back(-INF);
		for (auto &j : pp) vv.push_back(j.y);
		sort(vv.begin(),vv.end());BIT c;c.sz = vv.size();
		for (auto &j : pp)
			if (j.t == -1)
				c.add(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin(),j.x + j.y);
			else
				j.t = min(j.t,j.x + j.y -
				c.query(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin()));
		for (auto &j : pp) if (i & 1) j.x = -j.x;else j.y = -j.y;
	}
	n = 0;for (auto &j : pp) if (j.t != -1) a[++n] = j;
	for (int i = 1;i <= n;i++) a[i].x += a[i].y,a[i].y = a[i].x - 2 * a[i].y;
	for (int i = 1;i <= kk;i++)
		s[i].first += s[i].second,s[i].second = s[i].first - 2 * s[i].second;
	sort(s + 1,s + kk + 1);
	for (int i = 1;i <= kk;i++) modify(rt[i] = rt[i - 1],-INF,INF,s[i].second);
	sort(a + 1,a + n + 1,[](Node a,Node b) {return a.t > b.t;});a[n + 1].t = -INF;
	int mnx = INF,mxx = -INF,mny = INF,mxy = -INF,ans = a[1].t;
	for (int i = 1;i <= n;i++)
	{
		mnx = min(mnx,a[i].x);mny = min(mny,a[i].y);
		mxx = max(mxx,a[i].x);mxy = max(mxy,a[i].y);
		int l = max({a[i + 1].t,(mxx - mnx + 1) / 2,(mxy - mny + 1) / 2}),r = INF;
		if (!kk)
		{
			if (i == n) ans = l;
			continue;
		}
		while (l < r)
		{
			int mid = (l + r) >> 1,ex = mid - a[i + 1].t;
			if (qrect(mxx - mid - ex,mnx + mid + ex,mxy - mid - ex,mny + mid + ex))
				r = mid;
			else l = mid + 1;
		}
		int ex = l - a[i + 1].t,
		sum = qrect(mxx - l - ex,mnx + l + ex,mxy - l - ex,mny + l + ex);
		mxx -= l;mnx += l;mxy -= l;mny += l;
		if (mxx == mnx && mxy == mny && (mxx + mxy) % 2)
		{
			++l;--mxx;++mnx;--mxy;++mny;
		}
		else if (i != n)
		{
			if (mxx == mnx)
			{
				if ((mxx + mxy) & 1)
				// 对应的原坐标系中非整点，故应删去最外行，下同(但是去掉也可AC本题)
					sum -= qrect(mxx - ex,mnx + ex,mxy - ex,mxy - ex);
				if ((mxx + mny) & 1)
					sum -= qrect(mxx - ex,mnx + ex,mny + ex,mny + ex);
			}
			if (mxy == mny)
			{
				if ((mxy + mxx) & 1)
					sum -= qrect(mxx - ex,mxx - ex,mxy - ex,mny + ex);
				if ((mxy + mnx) & 1)
					sum -= qrect(mnx + ex,mnx + ex,mxy - ex,mny + ex);
			}
			if (!sum)
			{
				++l;--mxx;++mnx;--mxy;++mny;
			}
		}
		ans = min(ans,l);mxx += l;mnx -= l;mxy += l;mny -= l;
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 200005,INF = 200000000;
int n,kk;pair<int,int> s[N];struct Node {int x,y,t;} a[N];
inline int lowbit(int x) {return x & -x;}
struct BIT
{
	int sz,c[N];BIT() {memset(c,191,sizeof(c));}
	void add(int x,int v)
	{ while (x <= sz) c[x] = max(c[x],v),x += lowbit(x); }
	int query(int x)
	{
		int ret = c[0];while (x) { ret = max(ret,c[x]);x -= lowbit(x); }
		return ret;
	}
};
struct TNode {int lc,rc,v;} t[N << 5];int idx;
void modify(int &pos,int l,int r,int v)
{
	int tt = ++idx;t[tt] = t[pos];pos = tt;++t[tt].v;
	int mid = (l + r) >> 1;
	if (l == r) return;
	if (v <= mid) modify(t[pos].lc,l,mid,v);
	else modify(t[pos].rc,mid + 1,r,v);
}
int query(int pos,int l,int r,int ql,int qr)
{
	if (!t[pos].v || (ql <= l && r <= qr)) return t[pos].v;
	int mid = (l + r) >> 1;
	if (qr <= mid) return query(t[pos].lc,l,mid,ql,qr);
	else if (ql > mid) return query(t[pos].rc,mid + 1,r,ql,qr);
	return query(t[pos].lc,l,mid,ql,qr) + query(t[pos].rc,mid + 1,r,ql,qr);
}
int rt[N];
int qrect(int x1,int x2,int y1,int y2)
{
	if (y2 < -INF || y1 > INF) return 0;
	int pl = lower_bound(s + 1,s + kk + 1,pair<int,int>{x1,-INF}) - s - 1,
	pr = lower_bound(s + 1,s + kk + 1,pair<int,int>{x2 + 1,-INF}) - s - 1;
	return query(rt[pr],-INF,INF,y1,y2) - query(rt[pl],-INF,INF,y1,y2);
}
int main ()
{
	ios::sync_with_stdio(false);
	cin >> n >> kk;
	for (int i = 1;i <= n;i++)
		cin >> a[i].x >> a[i].y,a[i].t = INF;
	for (int i = 1;i <= kk;i++) cin >> s[i].first >> s[i].second;
	vector<Node> pp;for (int i = 1;i <= n;i++) pp.push_back(a[i]);
	for (int i = 1;i <= kk;i++) pp.push_back({s[i].first,s[i].second,-1});
	for (int i = 0;i < 4;i++)
	{
		sort(pp.begin(),pp.end(),[](Node a,Node b) {return a.x < b.x || (a.x == b.x
			&& (a.y < b.y || (a.y == b.y && a.t < b.t)));});
		vector<int> vv;vv.push_back(-INF);
		for (auto &j : pp) vv.push_back(j.y);
		sort(vv.begin(),vv.end());BIT c;c.sz = vv.size();
		for (auto &j : pp)
			if (j.t == -1)
				c.add(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin(),j.x + j.y);
			else
				j.t = min(j.t,j.x + j.y -
				c.query(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin()));
		for (auto &j : pp) if (i & 1) j.x = -j.x;else j.y = -j.y;
	}
	n = 0;for (auto &j : pp) if (j.t != -1) a[++n] = j;
	for (int i = 1;i <= n;i++) a[i].x += a[i].y,a[i].y = a[i].x - 2 * a[i].y;
	for (int i = 1;i <= kk;i++)
		s[i].first += s[i].second,s[i].second = s[i].first - 2 * s[i].second;
	sort(s + 1,s + kk + 1);
	for (int i = 1;i <= kk;i++) modify(rt[i] = rt[i - 1],-INF,INF,s[i].second);
	sort(a + 1,a + n + 1,[](Node a,Node b) {return a.t > b.t;});a[n + 1].t = -INF;
	int mnx = INF,mxx = -INF,mny = INF,mxy = -INF,ans = a[1].t;
	for (int i = 1;i <= n;i++)
	{
		mnx = min(mnx,a[i].x);mny = min(mny,a[i].y);
		mxx = max(mxx,a[i].x);mxy = max(mxy,a[i].y);
		int l = max({a[i + 1].t,(mxx - mnx + 1) / 2,(mxy - mny + 1) / 2}),r = INF;
		if (!kk)
		{
			if (i == n) ans = l;
			continue;
		}
		while (l < r)
		{
			int mid = (l + r) >> 1,ex = mid - a[i + 1].t;
			if (qrect(mxx - mid - ex,mnx + mid + ex,mxy - mid - ex,mny + mid + ex))
				r = mid;
			else l = mid + 1;
		}
		int ex = l - a[i + 1].t,
		sum = qrect(mxx - l - ex,mnx + l + ex,mxy - l - ex,mny + l + ex);
		mxx -= l;mnx += l;mxy -= l;mny += l;
		if (mxx == mnx && mxy == mny && (mxx + mxy) % 2)
		{
			++l;--mxx;++mnx;--mxy;++mny;
		}
		else if (i != n)
		{
			// if (mxx == mnx)
			// {
			// 	if ((mxx + mxy) & 1)
			// 		sum -= qrect(mxx - ex,mnx + ex,mxy - ex,mxy - ex);
			// 	if ((mxx + mny) & 1)
			// 		sum -= qrect(mxx - ex,mnx + ex,mny + ex,mny + ex);
			// }
			// if (mxy == mny)
			// {
			// 	if ((mxy + mxx) & 1)
			// 		sum -= qrect(mxx - ex,mxx - ex,mxy - ex,mny + ex);
			// 	if ((mxy + mnx) & 1)
			// 		sum -= qrect(mnx + ex,mnx + ex,mxy - ex,mny + ex);
			// }
			if (!sum)
			{
				++l;--mxx;++mnx;--mxy;++mny;
			}
		}
		ans = min(ans,l);mxx += l;mnx -= l;mxy += l;mny -= l;
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 200005,INF = 200000000;
int n,kk;pair<int,int> s[N];struct Node {int x,y,t;} a[N];
inline int lowbit(int x) {return x & -x;}
struct BIT
{
	int sz,c[N];BIT() {memset(c,191,sizeof(c));}
	void add(int x,int v)
	{ while (x <= sz) c[x] = max(c[x],v),x += lowbit(x); }
	int query(int x)
	{
		int ret = c[0];while (x) { ret = max(ret,c[x]);x -= lowbit(x); }
		return ret;
	}
};
struct TNode {int lc,rc,v;} t[N << 5];int idx;
void modify(int &pos,int l,int r,int v)
{
	int tt = ++idx;t[tt] = t[pos];pos = tt;++t[tt].v;
	int mid = (l + r) >> 1;
	if (l == r) return;
	if (v <= mid) modify(t[pos].lc,l,mid,v);
	else modify(t[pos].rc,mid + 1,r,v);
}
int query(int pos,int l,int r,int ql,int qr)
{
	if (!t[pos].v || (ql <= l && r <= qr)) return t[pos].v;
	int mid = (l + r) >> 1;
	if (qr <= mid) return query(t[pos].lc,l,mid,ql,qr);
	else if (ql > mid) return query(t[pos].rc,mid + 1,r,ql,qr);
	return query(t[pos].lc,l,mid,ql,qr) + query(t[pos].rc,mid + 1,r,ql,qr);
}
int rt[N];
int qrect(int x1,int x2,int y1,int y2)
{
	if (y2 < -INF || y1 > INF) return 0;
	int pl = lower_bound(s + 1,s + kk + 1,pair<int,int>{x1,-INF}) - s - 1,
	pr = lower_bound(s + 1,s + kk + 1,pair<int,int>{x2 + 1,-INF}) - s - 1;
	return query(rt[pr],-INF,INF,y1,y2) - query(rt[pl],-INF,INF,y1,y2);
}
int main ()
{
	ios::sync_with_stdio(false);
	cin >> n >> kk;
	for (int i = 1;i <= n;i++)
		cin >> a[i].x >> a[i].y,a[i].t = INF;
	for (int i = 1;i <= kk;i++) cin >> s[i].first >> s[i].second;
	vector<Node> pp;for (int i = 1;i <= n;i++) pp.push_back(a[i]);
	for (int i = 1;i <= kk;i++) pp.push_back({s[i].first,s[i].second,-1});
	for (int i = 0;i < 4;i++)
	{
		sort(pp.begin(),pp.end(),[](Node a,Node b) {return a.x < b.x || (a.x == b.x
			&& (a.y < b.y || (a.y == b.y && a.t < b.t)));});
		vector<int> vv;vv.push_back(-INF);
		for (auto &j : pp) vv.push_back(j.y);
		sort(vv.begin(),vv.end());BIT c;c.sz = vv.size();
		for (auto &j : pp)
			if (j.t == -1)
				c.add(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin(),j.x + j.y);
			else
				j.t = min(j.t,j.x + j.y -
				c.query(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin()));
		for (auto &j : pp) if (i & 1) j.x = -j.x;else j.y = -j.y;
	}
	n = 0;for (auto &j : pp) if (j.t != -1) a[++n] = j;
	for (int i = 1;i <= n;i++) a[i].x += a[i].y,a[i].y = a[i].x - 2 * a[i].y;
	for (int i = 1;i <= kk;i++)
		s[i].first += s[i].second,s[i].second = s[i].first - 2 * s[i].second;
	sort(s + 1,s + kk + 1);
	for (int i = 1;i <= kk;i++) modify(rt[i] = rt[i - 1],-INF,INF,s[i].second);
	sort(a + 1,a + n + 1,[](Node a,Node b) {return a.t > b.t;});a[n + 1].t = -INF;
	int mnx = INF,mxx = -INF,mny = INF,mxy = -INF,ans = a[1].t;
	for (int i = 1;i <= n;i++)
	{
		mnx = min(mnx,a[i].x);mny = min(mny,a[i].y);
		mxx = max(mxx,a[i].x);mxy = max(mxy,a[i].y);
		int l = max({a[i + 1].t,(mxx - mnx + 1) / 2,(mxy - mny + 1) / 2}),r = INF;
		if (!kk)
		{
			if (i == n) ans = l;
			continue;
		}
		while (l < r)
		{
			int mid = (l + r) >> 1,ex = mid - a[i + 1].t;
			if (qrect(mxx - mid - ex,mnx + mid + ex,mxy - mid - ex,mny + mid + ex))
				r = mid;
			else l = mid + 1;
		}
		int ex = l - a[i + 1].t,
		sum = qrect(mxx - l - ex,mnx + l + ex,mxy - l - ex,mny + l + ex);
		mxx -= l;mnx += l;mxy -= l;mny += l;
		if (mxx == mnx && mxy == mny && (mxx + mxy) % 2)
		{
			++l;--mxx;++mnx;--mxy;++mny;
		}
		else if (i != n)
		{
			if (mxx == mnx)
			{
				if ((mxx + mxy) & 1)
					sum -= qrect(mxx - ex,mnx + ex,mxy - ex,mxy - ex);
				if ((mxx + mny) & 1)
					sum -= qrect(mxx - ex,mnx + ex,mny + ex,mny + ex);
			}
			if (mxy == mny)
			{
				if ((mxy + mxx) & 1)
					sum -= qrect(mxx - ex,mxx - ex,mxy - ex,mny + ex);
				if ((mxy + mnx) & 1)
					sum -= qrect(mnx + ex,mnx + ex,mxy - ex,mny + ex);
			}
			if (!sum)
			{
				++l;--mxx;++mnx;--mxy;++mny;
			}
		}
		ans = min(ans,l);mxx += l;mnx -= l;mxy += l;mny -= l;
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 200005,INF = 200000000;
int n,kk;pair<int,int> s[N];struct Node {int x,y,t;} a[N];
inline int lowbit(int x) {return x & -x;}
struct BIT
{
	int sz,c[N];BIT() {memset(c,191,sizeof(c));}
	void add(int x,int v)
	{ while (x <= sz) c[x] = max(c[x],v),x += lowbit(x); }
	int query(int x)
	{
		int ret = c[0];while (x) { ret = max(ret,c[x]);x -= lowbit(x); }
		return ret;
	}
};
struct TNode {int lc,rc,v;} t[N << 5];int idx;
void modify(int &pos,int l,int r,int v)
{
	int tt = ++idx;t[tt] = t[pos];pos = tt;++t[tt].v;
	int mid = (l + r) >> 1;
	if (l == r) return;
	if (v <= mid) modify(t[pos].lc,l,mid,v);
	else modify(t[pos].rc,mid + 1,r,v);
}
int query(int pos,int l,int r,int ql,int qr)
{
	if (!t[pos].v || (ql <= l && r <= qr)) return t[pos].v;
	int mid = (l + r) >> 1;
	if (qr <= mid) return query(t[pos].lc,l,mid,ql,qr);
	else if (ql > mid) return query(t[pos].rc,mid + 1,r,ql,qr);
	return query(t[pos].lc,l,mid,ql,qr) + query(t[pos].rc,mid + 1,r,ql,qr);
}
int rt[N];
int qrect(int x1,int x2,int y1,int y2)
{
	if (y2 < -INF || y1 > INF) return 0;
	int pl = lower_bound(s + 1,s + kk + 1,pair<int,int>{x1,-INF}) - s - 1,
	pr = lower_bound(s + 1,s + kk + 1,pair<int,int>{x2 + 1,-INF}) - s - 1;
	return query(rt[pr],-INF,INF,y1,y2) - query(rt[pl],-INF,INF,y1,y2);
}
int main ()
{
	ios::sync_with_stdio(false);
	cin >> n >> kk;
	for (int i = 1;i <= n;i++)
		cin >> a[i].x >> a[i].y,a[i].t = INF;
	for (int i = 1;i <= kk;i++) cin >> s[i].first >> s[i].second;
	vector<Node> pp;for (int i = 1;i <= n;i++) pp.push_back(a[i]);
	for (int i = 1;i <= kk;i++) pp.push_back({s[i].first,s[i].second,-1});
	for (int i = 0;i < 4;i++)
	{
		sort(pp.begin(),pp.end(),[](Node a,Node b) {return a.x < b.x || (a.x == b.x
			&& (a.y < b.y || (a.y == b.y && a.t < b.t)));});
		vector<int> vv;vv.push_back(-INF);
		for (auto &j : pp) vv.push_back(j.y);
		sort(vv.begin(),vv.end());BIT c;c.sz = vv.size();
		for (auto &j : pp)
			if (j.t == -1)
				c.add(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin(),j.x + j.y);
			else
				j.t = min(j.t,j.x + j.y -
				c.query(lower_bound(vv.begin(),vv.end(),j.y) - vv.begin()));
		for (auto &j : pp) if (i & 1) j.x = -j.x;else j.y = -j.y;
	}
	n = 0;for (auto &j : pp) if (j.t != -1) a[++n] = j;
	for (int i = 1;i <= n;i++) a[i].x += a[i].y,a[i].y = a[i].x - 2 * a[i].y;
	for (int i = 1;i <= kk;i++)
		s[i].first += s[i].second,s[i].second = s[i].first - 2 * s[i].second;
	sort(s + 1,s + kk + 1);
	for (int i = 1;i <= kk;i++) modify(rt[i] = rt[i - 1],-INF,INF,s[i].second);
	sort(a + 1,a + n + 1,[](Node a,Node b) {return a.t > b.t;});a[n + 1].t = -INF;
	int mnx = INF,mxx = -INF,mny = INF,mxy = -INF,ans = a[1].t;
	for (int i = 1;i <= n;i++)
	{
		mnx = min(mnx,a[i].x);mny = min(mny,a[i].y);
		mxx = max(mxx,a[i].x);mxy = max(mxy,a[i].y);
		int l = max({a[i + 1].t,(mxx - mnx + 1) / 2,(mxy - mny + 1) / 2}),r = INF;
		if (!kk)
		{
			if (i == n) ans = l;
			continue;
		}
		cerr << mnx << ' ' << mny << ' ' << mxx << ' ' << mny << ' ' <<
		l << ' ' << r << endl;
		while (l < r)
		{
			int mid = (l + r) >> 1,ex = mid - a[i + 1].t;
			if (qrect(mxx - mid - ex,mnx + mid + ex,mxy - mid - ex,mny + mid + ex))
				r = mid;
			else l = mid + 1;
		}
		int ex = l - a[i + 1].t,
		sum = qrect(mxx - l - ex,mnx + l + ex,mxy - l - ex,mny + l + ex);
		mxx -= l;mnx += l;mxy -= l;mny += l;
		if (mxx == mnx && mxy == mny && (mxx + mxy) % 2)
		{
			++l;--mxx;++mnx;--mxy;++mny;
		}
		else if (i != n)
		{
			if (mxx == mnx)
			{
				if ((mxx + mxy) & 1)
					sum -= qrect(mxx - ex,mnx + ex,mxy - ex,mxy - ex);
				if ((mxx + mny) & 1)
					sum -= qrect(mxx - ex,mnx + ex,mny + ex,mny + ex);
			}
			if (mxy == mny)
			{
				if ((mxy + mxx) & 1)
					sum -= qrect(mxx - ex,mxx - ex,mxy - ex,mny + ex);
				if ((mxy + mnx) & 1)
					sum -= qrect(mnx + ex,mnx + ex,mxy - ex,mny + ex);
			}
			if (!sum)
			{
				++l;--mxx;++mnx;--mxy;++mny;
			}
		}
		ans = min(ans,l);mxx += l;mnx -= l;mxy += l;mny -= l;
	}
	cout << ans << endl;
	return 0;
}


#include"bits/stdc++.h"
#define inf 0x3f3f3f3f
#define MM 400400
#define NN 100100
#define y second
#define x first

using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> pi3;
template<typename A, typename B> inline void smin(A &a, const B &b) {if(a>b) a=b;}
template<typename A, typename B> inline void smax(A &a, const B &b) {if(a<b) a=b;}

int id[NN], LL[MM], RR[MM];
int x[NN], y[NN], xmn[MM], xmx[MM], ymn[MM], ymx[MM];

inline void select(int L, int mid, int R, int *val) {
	R--; int i, j, p, S, X;
	while(L+1<=R) {
		if(L+1==R) {
			if(val[id[L]]>val[id[R]]) swap(id[L], id[R]);
			return ;
		}
		S=L+1, X=S+rand()*rand()%(R-L);
		swap(id[L], id[X]);
		if(val[id[L]]>val[id[R]]) swap(id[L], id[R]);
		if(val[id[L]]>val[id[S]]) swap(id[L], id[S]);
		if(val[id[S]]>val[id[R]]) swap(id[S], id[R]);
		i=L, j=R, p=val[id[S]];
		while(true) {
			while(i<=R && val[id[i]]<=p) i++;
			while(j>=L && val[id[j]]>=p) j--;
			if(i>j) break; swap(id[i], id[j]);
		}
		if(mid<=j) R=j;
		else if(mid>=i) L=i;
		else break;
	}
}

inline void build(int u, int L, int R, int dp=0) {
	LL[u]=L, RR[u]=R;
	if(L+1==R) {
		xmn[u]=xmx[u]=x[id[L]];
		ymn[u]=ymx[u]=y[id[L]];
		return ;
	}
	int ls=u<<1, rs=ls|1, mid=L+R>>1;

	if(dp) select(L, mid, R, x);
	else select(L, mid, R, y);

	dp^=1;
	build(ls, L, mid, dp);
	build(rs, mid, R, dp);

	xmn[u]=min(xmn[ls], xmn[rs]), xmx[u]=max(xmx[ls], xmx[rs]);
	ymn[u]=min(ymn[ls], ymn[rs]), ymx[u]=max(ymx[ls], ymx[rs]);
}

pi3 p[NN];
int X, Y, mn;

inline void calc(int u) {
	int x_x=0, y_y=0;
	if(X>xmx[u]) x_x=X-xmx[u];
	if(X<xmn[u]) x_x=xmn[u]-X;
	if(Y>ymx[u]) y_y=Y-ymx[u];
	if(Y<ymn[u]) y_y=ymn[u]-Y;
	if(max(x_x, y_y)>mn) return ;
	int L=LL[u], R=RR[u];
	if(L+1==R) {
		smin(mn, max(abs(X-x[id[L]]), abs(Y-y[id[L]])));
		return ;
	}
	int ls=u<<1;
	calc(ls), calc(ls|1);
}

int n, k, ax, ay, bx, by;

inline bool in(int u) {
	if( bx<xmn[u] || xmx[u]<ax  ||  by<ymn[u] || ymx[u]<ay) return false;
	if(ax<=xmn[u] && xmx[u]<=bx && ay<=ymn[u] && ymx[u]<=by) return true;
	if(LL[u]+1==RR[u]) return false;
	int ls=u<<1;
	if(in(ls)) return true;
	return in(ls|1);
}

inline bool can(int d) {
	ax=ay=-inf, bx=by=inf;
	for(int i=1; i<=n; i++) {
		if(ax<=bx && ay<=by) {
			if(k && p[i].y<=d) {
				int T=d-p[i].y;
				ax-=T, ay-=T, bx+=T, by+=T;
				if(in(1)) return true;
				ax+=T, ay+=T, bx-=T, by-=T;
			}
		}
		else return false;
		X=p[i].x.x, Y=p[i].x.y;
		smax(ax, X-d), smin(bx, X+d);
		smax(ay, Y-d), smin(by, Y+d);
	}
	return ax<=bx && ay<=by;
}

main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	srand(time(0));

	scanf("%d %d", &n, &k);
	for(int i=1, x, y; i<=n; i++) {
		scanf("%d %d", &x, &y);
		p[i].x={x-y, x+y};
	}
	if(k) {
		for(int i=1, x, y; i<=k; i++) {
			scanf("%d %d", &x, &y);
			::x[i]=x-y, ::y[i]=x+y, id[i]=i;
		}
		build(1, 1, k+1);

		for(int i=1; i<=n; i++) {
			mn=inf;
			X=p[i].x.x, Y=p[i].x.y;
			calc(1);
			p[i].y=mn;
		}
		sort(p+1, p+n+1, [](pi3 a, pi3 b) {return a.y>b.y;});
	}

	int st=-1, ed=200000000;
	while(ed-st>1) {
		int md=st+ed>>1;
		if(can(md)) ed=md;
		else st=md;
	}
	printf("%d", ed);
}