#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <deque>
#include <chrono>
#include <bitset>
using namespace std;

typedef int li;
typedef long double ld;

const li MAX = (li)1e6 + 100;
li inf = (li)1e18;
li mod = (li)1e9 + 7;
li n, m, suf[MAX];
li ans = 0;
struct node {
    li l, r, mid;
    li maxi;
    node* son_l;
    node* son_r;
    node(li a, li b) {
        l = a;
        r = b;
        mid = (a + b) / 2;
        son_l = 0;
        son_r = 0;
        maxi = 0;
    }
};

void build(node* root) {
    if (root->l == root->r) return;
    root->son_l = new node(root->l, root->mid);
    root->son_r = new node(root->mid + 1, root->r);
    build(root->son_l);
    build(root->son_r);
}

void mx(node* root, li bl, li br, li val) {
    if (bl > br) return;
    else if (root->l == bl && root->r == br) {
        root->maxi = max(root->maxi, val);
    }
    else {
        mx(root->son_l, bl, min(br, root->mid), val);
        mx(root->son_r, max(bl, root->mid + 1), br, val);
    }
}

void upd(node* root) {
    if (root->l == root->r) {
        ans = min(ans, root->l + root->maxi);
    }
    else {
        root->son_l->maxi = max(root->son_l->maxi, root->maxi);
        root->son_r->maxi = max(root->son_r->maxi, root->maxi);
        upd(root->son_l);
        upd(root->son_r);
    }
}

void solve() {
    node* root = new node(1, li(1e6 + 5));
    build(root);
    cin >> n >> m;
    vector<pair<li, li>> rob(n + 1), l(m + 1);
    for (int i = 1; i <= n; i++) {
        cin >> rob[i].first >> rob[i].second;
    }
    for (int i = 1; i <= m; i++) {
        cin >> l[i].first >> l[i].second;
    }
    sort(l.begin(), l.end());
    suf[m] = l[m].second;
    for (int i = m - 1; i >= 0; i--) {
        suf[i] = max(l[i].second, suf[i + 1]);
    }
    suf[m + 1] = -1;
    for (int i = 1; i <= n; i++) {
        li x = rob[i].first;
        li y = rob[i].second;
        for (int j = 0; j <= m; j++) {
            li d = max(li(1), l[j].first - x + 1);
            if (d) {
                li lef = d;
                li rig;
                if (j == m) rig = (li)1e6 + 5;
                else rig = max(li(0), l[j + 1].first - x);
                li ad = max(li(0), suf[j + 1] - y + 1);
                if (ad)
                mx(root, lef, rig, ad);
            }
        }
        for (int j = 1; j <= m; j++) {
            ans = max(ans, l[j].second - y + 1);
        }
    }

    upd(root);
    cout << ans;
}

int main() {
    ios::sync_with_stdio(0);
    li q;
    q = 1;
    while (q--)solve();
    return 0;
}


//#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <deque>
#include <chrono>
#include <bitset>
using namespace std;

typedef int li;
typedef long double ld;

const li MAX = (li)1e6 + 100;
li inf = (li)1e18;
li mod = (li)1e9 + 7;
li n, m, suf[MAX], ans[MAX];

void solve() {
    cin >> n >> m;
    vector<pair<li, li>> rob(n + 1), l(m + 1);
    vector<pair<pair<li, li>, li>> segs;
    for (int i = 1; i <= n; i++) {
        cin >> rob[i].first >> rob[i].second;
    }
    for (int i = 1; i <= m; i++) {
        cin >> l[i].first >> l[i].second;
    }
    sort(l.begin(), l.end());
    suf[m] = l[m].second;
    for (int i = m - 1; i >= 0; i--) {
        suf[i] = max(l[i].second, suf[i + 1]);
    }
    suf[m + 1] = -1e9;
    l[0].first = -1;
    for (int i = 1; i <= n; i++) {
        li x = rob[i].first;
        li y = rob[i].second;
        for (int j = 0; j <= m; j++) {
            li lef = max(li(0), l[j].first - x + 1);
            li rig;
            if (j == m) rig = MAX;
            else rig = max(li(0), l[j + 1].first - x);
            li v = max(li(0), suf[j + 1] - y + 1);
            if (rig >= lef && v) {
                segs.push_back({ { lef, 0 }, v });
                segs.push_back({ {rig + 1, 1}, v });
            }
        }
    }

    sort(segs.begin(), segs.end());
    li uk = 0;
    multiset<li> vals;
    vals.insert(0);
    for (int i = 0; i < MAX; i++) {
        while (uk < segs.size() && segs[uk].first.first <= i) {
            if (segs[uk].first.second == 0) vals.insert(segs[uk].second);
            else vals.erase(vals.find(segs[uk].second));
            uk++;

        }
        ans[i] = i + *vals.rbegin();

    }
    li out = ans[0];
    for (int i = 1; i < MAX; i++) out = min(out, ans[i]);
    cout << out;
}

int main() {
    ios::sync_with_stdio(0);
    li q;
    q = 1;
    while (q--)solve();
    return 0;
}


//#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <deque>
#include <chrono>
#include <bitset>
using namespace std;

typedef int li;
typedef long double ld;

const li MAX = (li)1e6 + 100;
li inf = (li)1e18;
li mod = (li)1e9 + 7;
li n, m, suf[MAX], ans[MAX];

void solve() {
    cin >> n >> m;
    vector<pair<li, li>> rob(n + 1), l(m + 1);
    vector<pair<pair<li, li>, li>> segs;
    for (int i = 1; i <= n; i++) {
        cin >> rob[i].first >> rob[i].second;
    }
    for (int i = 1; i <= m; i++) {
        cin >> l[i].first >> l[i].second;
    }
    sort(l.begin(), l.end());
    suf[m] = l[m].second;
    for (int i = m - 1; i >= 0; i--) {
        suf[i] = max(l[i].second, suf[i + 1]);
    }
    suf[m + 1] = -1;
    l[0].first = -1;
    for (int i = 1; i <= n; i++) {
        li x = rob[i].first;
        li y = rob[i].second;
        for (int j = 0; j <= m; j++) {
            li lef = max(li(0), l[j].first - x + 1);
            li rig;
            if (j == m) rig = MAX;
            else rig = max(li(0), l[j + 1].first - x);
            li v = max(li(0), suf[j + 1] - y + 1);
            if (rig >= lef && v) {
                segs.push_back({ { lef, 0 }, v });
                segs.push_back({ {rig + 1, 1}, v });
            }
        }
    }

    sort(segs.begin(), segs.end());
    li uk = 0;
    multiset<li> vals;
    vals.insert(1e8);
    for (int i = 0; i < MAX; i++) {
        while (uk < segs.size() && segs[uk].first.first <= i) {
            if (segs[uk].first.second == 0) vals.insert(segs[uk].second);
            else vals.erase(vals.find(segs[uk].second));
            uk++;

        }
        ans[i] = i + *vals.rbegin();

    }
    li out = ans[0];
    for (int i = 1; i < MAX; i++) out = min(out, ans[i]);
    cout << out;
}

int main() {
    ios::sync_with_stdio(0);
    li q;
    q = 1;
    while (q--)solve();
    return 0;
}


#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <deque>
#include <chrono>
#include <bitset>
using namespace std;

typedef int li;
typedef long double ld;

const li MAX = (li)1e6 + 100;
li inf = (li)1e18;
li mod = (li)1e9 + 7;
li n, m, suf[(li)2e4], ans[MAX], cnt[MAX];
vector<pair<li, li>> t[MAX];
map<li, li> coor;
void solve() {
    cin >> n >> m;
    vector<pair<pair<li, li>, li>> segs;
    vector<pair<li, li>> rob(n + 1), l(m + 1);
    for (int i = 1; i <= n; i++) {
        cin >> rob[i].first >> rob[i].second;
    }
   for (int i = 1; i <= m; i++) {
        cin >> l[i].first >> l[i].second;
        coor[l[i].first] = max(coor[l[i].first], l[i].second);
   }
   l.clear();
   coor[(li)1e6 + 1] = -1;
   l.clear();
   l.push_back({ -1, 0 });
   for (auto u : coor) {
       l.push_back(u);
   }

    m = l.size();
    suf[m - 1] = l.back().second;
    for (int i = m - 2; i >= 0; i--) {
        suf[i] = max(suf[i + 1], l[i].second);
    }
    for (int i = 1; i <= n; i++) {
        li cur = 1;
        for (int j = 1; j < m; j++) {
            if (l[j].first < rob[i].first) cur = j + 1;
        }
        for (int j = cur; j < m; j++) {
            li lef = max(li(0), l[j - 1].first - rob[i].first + 1);
            li rig = (l[j].first - rob[i].first);
            li ad = max(li(0), suf[j] - rob[i].second + 1);
            if (ad) {
                t[lef].push_back({ 0, ad });
                t[rig + 1].push_back({ 1, ad });
            }
        }
    }
    set<li> vals = { 0 };
    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < t[i].size(); j++) {
            if (t[i][j].first == 0) {
                if (!cnt[t[i][j].second])
                vals.insert(t[i][j].second);
                cnt[t[i][j].second]++;
            }
            else {
                cnt[t[i][j].second]--;
                if (!cnt[t[i][j].second])
                vals.erase(t[i][j].second);
            }
        }
        ans[i] = i + *vals.rbegin();
    }
    li out = ans[0];
    for (int i = 1; i < MAX; i++) out = min(out, ans[i]);
    cout << out;
}

int main() {
    ios::sync_with_stdio(0);
    li q;
    q = 1;
    while (q--)solve();
    return 0;
}


//#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <deque>
#include <chrono>
#include <bitset>
using namespace std;

typedef int li;
typedef long double ld;

const li MAX = (li)1e6 + 100;
li inf = (li)1e18;
li mod = (li)1e9 + 7;
li n, m, suf[MAX], ans[MAX];

void solve() {
    cin >> n >> m;
    vector<pair<li, li>> rob(n + 1), l(m + 1);
    vector<pair<pair<li, li>, li>> segs;
    for (int i = 1; i <= n; i++) {
        cin >> rob[i].first >> rob[i].second;
    }
    for (int i = 1; i <= m; i++) {
        cin >> l[i].first >> l[i].second;
    }
    sort(l.begin(), l.end());
    suf[m] = l[m].second;
    for (int i = m - 1; i >= 0; i--) {
        suf[i] = max(l[i].second, suf[i + 1]);
    }
    suf[m + 1] = -1;
    l[0].first = -1;
    for (int i = 1; i <= n; i++) {
        li x = rob[i].first;
        li y = rob[i].second;
        for (int j = 0; j < m; j++) {
            li lef = max(li(0), l[j].first - x + 1);
            li rig = max(li(0), l[j + 1].first - x);
            li v = max(li(0), suf[j + 1] - y + 1);
            if (rig >= lef && v) {
                segs.push_back({ { lef, 0 }, v });
                segs.push_back({ {rig + 1, 1}, v });
            }
        }
    }

    sort(segs.begin(), segs.end());
    li uk = 0;
    multiset<li> vals;
    vals.insert(0);
    for (int i = 0; i < MAX; i++) {
        while (uk < segs.size() && segs[uk].first.first <= i) {
            if (segs[uk].first.second == 0) vals.insert(segs[uk].second);
            else vals.erase(vals.find(segs[uk].second));
            uk++;

        }
        ans[i] = i + *vals.rbegin();

    }
    li out = ans[0];
    for (int i = 1; i < MAX; i++) out = min(out, ans[i]);
    cout << out;
}

int main() {
    ios::sync_with_stdio(0);
    li q;
    q = 1;
    while (q--)solve();
    return 0;
}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int l = 0, r = 1e6 + 1, ans = 1e6 + 1;
	while(l <= r){
		vector<pii> ca = a;
		int mid = l + r >> 1;
		rep(i, sz(a)) ca[i].F += x, ca[i].S += mid;
		sort(all(ca));
		int j = 0;
		bool bad = 0;
		for(int i = 0; i < n; ++i){
			while(j < m and b[j].F < ca[i].F) j++;
			if(j == m) break;
			else{
				if(suf[j] >= ca[i].S) bad = 1;
			}
 		}
 		if(bad){
 			l = mid + 1;
 		}
 		else{
 			ans = mid;
 			r = mid - 1;
 		}
	}
	return x + ans;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	sort(begin(b), end(b));
	suf[m - 1] = b[m - 1].S;
	for(int i = m - 2; i >= 0; --i){
		suf[i] = max(suf[i + 1], b[i].S);
	}
	int l = 0, r = 1e6 + 1;
	while(r - l > 3){
		int m1 = l + (r - l) / 3;
		int m2 = r - (r - l) / 3;
		if(f(m1) < f(m2)) r = m2;
		else l = m1;
	}
	int ans = inf;
	for(int i = l; i <= r; ++i) {
		ans = min(ans, f(i));
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	vector<int> vals;
	sort(begin(b), end(b));
	sort(begin(a), end(a));
	int nxt[m];
	repr(i, sz(b)){
		if(i == m - 1) nxt[i] = i + 1;
		else{
			if(b[i].F == b[i + 1].F) nxt[i] = nxt[i + 1];
			else nxt[i] = i + 1;
		}
	}
	suf[m - 1] = b[m - 1].S;
	for(int i = m - 2; i >= 0; --i){
		suf[i] = max(suf[i + 1], b[i].S);
	}
	vector<int> ans(1e6 + 2, 0);
	rep(i, n){
		rep(j, m){
			if(b[j].F >= a[i].F)
			{
				ckmax(ans[b[j].F - a[i].F], max(0, suf[j] - a[i].S + 1));
			}
			if(b[j].F > a[i].F and nxt[j] != m){
				ckmax(ans[b[j].F - a[i].F + 1], max(0, suf[nxt[j]] - a[i].S + 1));
			}
		}
	}
	int res = inf;
	for(int i = 1e6 + 1; i >= 1; --i){
		ans[i] = max(ans[i + 1], ans[i]);
		res = min(res, i + ans[i]);
	}
	cout << res;

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		set<int> tries;
		tries.insert(0);
		vector<int> verts;
		for(auto it : tries) verts.pb(it);
		rep(i, n){
			rep(j, m){
				if(b[j].F >= a[i].F)
					tries.insert(b[j].F - a[i].F + 1);
			}
		}
		for(auto it : tries) verts.pb(it);
		sort(begin(a), end(a));
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		for(int x : verts) {
			ans = min(ans, f(x));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int l = 0, r = 1e6 + 1, ans = 1e6 + 1;
	while(l <= r){
		vector<pii> ca = a;
		int mid = l + r >> 1;
		rep(i, sz(a)) ca[i].F += x, ca[i].S += mid;
		sort(all(ca));
		int j = 0;
		bool bad = 0;
		for(int i = 0; i < n; ++i){
			while(j < m and b[j].F < ca[i].F) j++;
			if(j == m) break;
			else{
				if(suf[j] >= ca[i].S) bad = 1;
			}
 		}
 		if(bad){
 			l = mid + 1;
 		}
 		else{
 			ans = mid;
 			r = mid - 1;
 		}
	}
	return x + ans;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(r - l > 3){
			int m1 = l + (r - l) / 3;
			int m2 = r - (r - l) / 3;
			if(f(m1) < f(m2)) r = m2;
			else l = m1;
		}
		for(int i = max(0, l - 100); i <= r + 100; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	vector<int> vals;
	sort(begin(b), end(b));
	sort(begin(a), end(a));
	int nxt[m];
	repr(i, sz(b)){
		if(i == m - 1) nxt[i] = i + 1;
		else{
			if(b[i].F == b[i + 1].F) nxt[i] = nxt[i + 1];
			else nxt[i] = i + 1;
		}
	}
	suf[m - 1] = b[m - 1].S;
	for(int i = m - 2; i >= 0; --i){
		suf[i] = max(suf[i + 1], b[i].S);
	}
	vector<int> ans(1e6 + 2, 0);
	rep(i, n){
		rep(j, m){
			if(b[j].F >= a[i].F)
			{
				ckmax(ans[b[j].F - a[i].F], max(0, suf[j] - a[i].S + 1));
			}
			if(b[j].F > a[i].F and nxt[j] != m){
				ckmax(ans[b[j].F - a[i].F + 1], max(0, suf[nxt[j]] - a[i].S + 1));
			}
		}
	}
	int res = inf;
	for(int i = 1e6 - 1; i >= 1; --i){
		ans[i] = max(ans[i + 1], ans[i]);
		res = min(res, i + ans[i]);
	}
	cout << res;

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(a), end(a));
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(r - l > 3){
			int m1 = l + (r - l) / 3;
			int m2 = r - (r - l) / 3;
			if(f(m1) < f(m2)) r = m2;
			else l = m1;
		}
		for(int i = max(0, l - 100); i <= r + 100; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int l = 0, r = 1e6 + 1, ans = 1e6 + 1;
	while(l <= r){
		vector<pii> ca = a;
		int mid = l + r >> 1;
		rep(i, sz(a)) ca[i].F += x, ca[i].S += mid;
		sort(all(ca));
		int j = 0;
		bool bad = 0;
		for(int i = 0; i < n; ++i){
			while(j < m and b[j].F < ca[i].F) j++;
			if(j == m) break;
			else{
				if(suf[j] >= ca[i].S) bad = 1;
			}
 		}
 		if(bad){
 			l = mid + 1;
 		}
 		else{
 			ans = mid;
 			r = mid - 1;
 		}
	}
	return x + ans;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(r - l > 3){
			int m1 = l + (r - l) / 3;
			int m2 = r - (r - l) / 3;
			if(f(m1) < f(m2)) r = m2;
			else l = m1;
		}
		for(int i = max(0, l - 1000); i <= r + 1000; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 1, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(a), end(a));
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(l <= r){
			int m = l + r >> 1;
			if(f(m) > f(m - 1)) r = m - 1;
			else l = m + 1;
		}
		for(int i = max(0, l - 100); i <= r + 100; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	vector<int> vals;
	sort(begin(b), end(b));
	sort(begin(a), end(a));
	// int nxt[m];
	// repr(i, m){
	// 	if(i == m - 1) nxt[i] = i + 1;
	// 	else{
	// 		if(b[i].F == b[i + 1].F) nxt[i] = nxt[i + 1];
	// 		else nxt[i] = i + 1;
	// 	}
	// }
	suf[m - 1] = b[m - 1].S;
	for(int i = m - 2; i >= 0; --i){
		suf[i] = max(suf[i + 1], b[i].S);
	}
	vector<int> ans(1e6 + 10, 0);
	rep(i, n){
		rep(j, m){
			if(b[j].F >= a[i].F)
			{
				ckmax(ans[b[j].F - a[i].F + 1], max(0, suf[j] - a[i].S + 1));
			}
			// if(b[j].F > a[i].F and nxt[j] != m){
			// 	ckmax(ans[b[j].F - a[i].F + 1], max(0, suf[nxt[j]] - a[i].S + 1));
			// }
		}
	}
	int res = inf;
	for(int i = 1e6 + 5; i >= 1; --i){
		ans[i] = max(ans[i + 1], ans[i]);
		res = min(res, i - 1 + ans[i]);
	}
	cout << min(res, f(0));

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int l = 0, r = 1e6 + 1, ans = 1e6 + 1;
	while(l <= r){
		vector<pii> ca = a;
		int mid = l + r >> 1;
		rep(i, sz(a)) ca[i].F += x, ca[i].S += mid;
		sort(all(ca));
		int j = 0;
		bool bad = 0;
		for(int i = 0; i < n; ++i){
			while(j < m and b[j].F < ca[i].F) j++;
			if(j == m) break;
			else{
				if(suf[j] >= ca[i].S) bad = 1;
			}
 		}
 		if(bad){
 			l = mid + 1;
 		}
 		else{
 			ans = mid;
 			r = mid - 1;
 		}
	}
	return x + ans;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(r - l > 3){
			int m1 = l + (r - l) / 3;
			int m2 = r - (r - l) / 3;
			if(f(m1) < f(m2)) r = m2;
			else l = m1;
		}
		for(int i = l; i <= r; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define pb push_back
#define mp make_pair
#define cotu cout
#define itn int
#define Red ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define F first
#define S second
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define repst(i, n) for(auto it = n.begin(); it != n.end(); ++it)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
#define setp(x) fixed << setprecision(x)
#define ordered_set tree<pair<long double, int> , null_type,less<pair<long double, int> >, rb_tree_tag,tree_order_statistics_node_update>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;

const int inf = int(1e9);
const ll INF = ll(1e16);
const int mod = inf + 7;
const int N = 1e5 + 555; // TL MB
const double PI = acos(-1.0);
void mul(ll &x, ll y){
	x *= y;
	if(x >= mod) x %= mod;
}
ll bp(ll a, ll n){
	ll r = 1;
	while(n){
		if(n & 1) mul(r, a);
		mul(a, a);
		n >>= 1;
	}
	return r;
}
template<typename T_vector> // neal
void output_vector(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
    if (start < 0) start = 0;
    if (end < 0) end = int(v.size());

    for (int i = start; i < end; i++)
        cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
}

vector<pii> a, b;
vector<int> suf;
int n, m;
int f(int x){
	int j = 0;
	int mx = 0;
	for(int i = 0; i < n; ++i){
		while(j < m and b[j].F < a[i].F + x) j++;
		if(j != m) mx = max(mx, max(0, suf[j] - a[i].S + 1));
	}
	return x + mx;
}
void solve()
{
	cin >> n >> m;
	a.resize(n), b.resize(m);
	suf.resize(m);
	rep(i, n) cin >> a[i].F >> a[i].S;
	rep(i, m) cin >> b[i].F >> b[i].S;
	int l = 0, r = 1e6 + 1, ans = inf;
	for(int it = 0; it < 2; ++it){
		sort(begin(a), end(a));
		sort(begin(b), end(b));
		suf[m - 1] = b[m - 1].S;
		for(int i = m - 2; i >= 0; --i){
			suf[i] = max(suf[i + 1], b[i].S);
		}
		while(r - l > 3){
			int m1 = l + (r - l) / 3;
			int m2 = r - (r - l) / 3;
			if(f(m1) < f(m2)) r = m2;
			else l = m1;
		}
		for(int i = max(0, l - 10000); i <= r + 10000; ++i) {
			ans = min(ans, f(i));
		}
		for(int i = 0; i < n; ++i) swap(a[i].F, a[i].S);
		for(int i = 0; i < m; ++i) swap(b[i].F, b[i].S);
	}
	cout << ans << '\n';

}

int main()
{
	// freopen("input.txt", "r", stdin);
	// freopen("output.txt", "w", stdout);
    Red;
  	int T = 1;
  	// cin >> T;
  	for(int i = 1; i <= T; ++i){
  		solve();
  	}
  	return 0;

}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    R.resize(N);
    rep(i, N) cin >> R[i].ff >> R[i].ss;

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    int ans = INT_MAX;
    rep(i, 1000100) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M, x, y, H[10000001];
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b)
    {
        v = max(b.v, x);
    }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    int X = 0;
    R.resize(N);
    rep(i, N) { cin >> R[i].ff >> R[i].ss; X = max(X, R[i].ff); }

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1200001);
    STL<Node> stl(v);

    rep(i, N) rep(j, M)
    {
        if (R[i].ff <= S[j].ff)
            stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);
    }

    int ans = INT_MAX;
    rep(i, 1200001 - X) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M, x, y, H[10000001];
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b)
    {
        v = max(b.v, x);
    }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    int X = 0;
    R.resize(N);
    rep(i, N) { cin >> R[i].ff >> R[i].ss; X = max(X, R[i].ff); }

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1200001);
    STL<Node> stl(v);

    rep(i, N) rep(j, M)
    {
        if (R[i].ff <= S[j].ff)
            stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);
    }

    int ans = INT_MAX;
    rep(i, 110000 - X) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    int X = 0;
    R.resize(N);
    rep(i, N) { cin >> R[i].ff >> R[i].ss; X = max(X, R[i].ff); }

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    assert(-1 == 0);

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    int ans = INT_MAX;
    rep(i, 1000100 - X) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M, x, y, H[10000001];
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    int X = 0;
    R.resize(N);
    rep(i, N) { cin >> R[i].ff >> R[i].ss; X = max(X, R[i].ff); }

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    int ans = INT_MAX;
    rep(i, 1000100 - X) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    R.resize(N);
    rep(i, N) cin >> R[i].ff >> R[i].ss;

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    cout << -1 << '\n';
    return 0;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    cout << -1 << '\n';
    return 0;

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    cout << -1 << '\n';
    return 0;

    int ans = INT_MAX;
    rep(i, 1000100) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    R.resize(N);
    rep(i, N) cin >> R[i].ff >> R[i].ss;

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    cout << -1 << '\n';
    return 0;

    int ans = INT_MAX;
    rep(i, 1000100) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v, int N) : st(N * 4 + 5) { n = N; build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    R.resize(N);
    rep(i, N) cin >> R[i].ff >> R[i].ss;

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v, 1001000);

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    int ans = INT_MAX;
    rep(i, 1000100) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


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

#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define ff first
#define ss second

int N, M;
vector<pair<int, int>> R, S;

struct Node
{
    int v = 0, lzv = 0;
    bool lz = false;
    Node() : v(0) {}
    Node(int x) : v(x) {}
    Node(const Node &a, const Node &b) : v(max(a.v, b.v)) {}
    Node(int x, const Node &b) { v = max(b.v, x); }
};

template <class node>
struct STL
{
    vector<node> st; int n;

    void build(int u, int i, int j, vector<node> &arr)
    {
        if (i == j) { st[u] = arr[i]; return; }
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        build(l, i, m, arr), build(r, m + 1, j, arr);
        st[u] = node(st[l], st[r]);
    }
    void push(int u, int i, int j, int x)
    {
        st[u] = node(x, st[u]);
        if (i == j) return;
        st[u * 2 + 1].lz = 1, st[u * 2 + 1].lzv = max(st[u * 2 + 1].lzv, x);
        st[u * 2 + 2].lz = 1, st[u * 2 + 2].lzv = max(st[u * 2 + 2].lzv, x);
    }
    node query(int a, int b, int u, int i, int j)
    {
        if (j < a || b < i) return node();
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) return st[u];
        return node(query(a, b, l, i, m), query(a, b, r, m + 1, j));
    }
    void update(int a, int b, int v, int u, int i, int j)
    {
        if (j < a || b < i) return;
        int m = (i + j) / 2, l = u * 2 + 1, r = u * 2 + 2;
        if (st[u].lz) push(u, i, j, st[u].lzv);
        if (a <= i && j <= b) { push(u, i, j, v); return; }
        update(a, b, v, l, i, m);
        update(a, b, v, r, m + 1, j);
        st[u] = node(st[l], st[r]);
    }

    STL(vector<node> &v) : n(v.size()), st(n * 4 + 5) { build(0, 0, n - 1, v); }
    node query(int a, int b) { return query(a, b, 0, 0, n - 1); }
    void update(int a, int b, int v) { update(a, b, v, 0, 0, n - 1); }
};

int main()
{
    cin >> N >> M;

    R.resize(N);
    rep(i, N) cin >> R[i].ff >> R[i].ss;

    S.resize(M);
    rep(i, M) cin >> S[i].ff >> S[i].ss;

    vector<Node> v(1001000);
    STL<Node> stl(v);

    cout << -1 << '\n';
    return 0;

    rep(i, N) rep(j, M) if (R[i].ff <= S[j].ff)
        stl.update(0, S[j].ff - R[i].ff, S[j].ss + 1 - R[i].ss);

    cout << -1 << '\n';
    return 0;

    int ans = INT_MAX;
    rep(i, 1000100) ans = min(ans, i + stl.query(i, i).v);

    cout << ans << '\n';
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(iip a, iip b)
{
	return a.first<b.first;
}

bool cmp2(iip a, iip b)
{
	return a.second<b.second;
}

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	sort(robs.begin(), robs.end(), cmp1);
	sort(srs.rbegin(), srs.rend(), cmp1);
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	int lans11 =0, rans11 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans11+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans11+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans11 += lmn, rans11+=rmn;
	}

	sort(robs.begin(), robs.end(), cmp2);
	sort(srs.rbegin(), srs.rend(), cmp2);
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int lans22 =0, rans22 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans22+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans22+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans22 += lmn, rans22+=rmn;
	}
	int final_ans = min(min(lans11+rans11, lans22+rans22), min(lans+rans, lans2+rans2));
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(iip a, iip b)
{
	return a.first<b.first;
}

bool cmp2(iip a, iip b)
{
	return a.second<b.second;
}

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	sort(robs.begin(), robs.end(), cmp1);
	sort(srs.rbegin(), srs.rend(), cmp1);
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	sort(robs.begin(), robs.end(), cmp2);
	sort(srs.rbegin(), srs.rend(), cmp2);
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int final_ans = min(lans+rans, lans2+rans2);
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(iip a, iip b)
{
	return a.first<b.first;
}

bool cmp2(iip a, iip b)
{
	return a.second<b.second;
}

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	int mxl=0,mxr=0;
	for(int i=0;i<rob;i++){
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first+1);
			int rdif = max(0, srs[j].second-robs[i].second+1);
			if(ldif < rdif){
				mxl = max(mxl, ldif);
			}
			else if(ldif == rdif){
				mxl = max(mxl, ldif);
				mxr = max(mxr, rdif);
			}
			else mxr = max(mxr, rdif);
		}
	}
	sort(robs.begin(), robs.end(), cmp1);
	sort(srs.rbegin(), srs.rend(), cmp1);
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	int lans11 =0, rans11 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans11+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans11+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans11 += lmn, rans11+=rmn;
	}

	sort(robs.begin(), robs.end(), cmp2);
	sort(srs.rbegin(), srs.rend(), cmp2);
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int lans22 =0, rans22 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans22+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans22+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans22 += lmn, rans22+=rmn;
	}
	int final_ans = min(min(lans11+rans11, lans22+rans22), min(lans+rans, lans2+rans2));
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 1000009
ll dp[MX];

void input_fun()
{
	ll rob, sr;
	cin>>rob>>sr;
	vector<llp> robs(rob), srs(sr);
	for(ll i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(ll i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	for(int i=0;i<rob;i++){
		for(int j=0;j<sr;j++){
			if(srs[j].first<robs[i].first || srs[j].second<robs[i].second)continue;
			ll dif1 = max(0LL, srs[j].first-robs[i].first);
			ll dif2 = max(0LL, srs[j].second-robs[i].second);
			dp[dif1] = dif2+1;
		}
	}
	for(int i=MX-8;i>=0;i--)dp[i] = max(dp[i], dp[i+1]);
	ll ans = MX;
	for(int i=MX-5;i>=0;i--){
		ans = min(ans, i+dp[i]);
	}
	cout<<ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int final_ans = min(lans+rans, lans2+rans2);
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(iip a, iip b)
{
	return a.first<b.first;
}

bool cmp2(iip a, iip b)
{
	return a.second<b.second;
}

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	sort(robs.rbegin(), robs.rend(), cmp1);
	sort(srs.begin(), srs.end(), cmp1);
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	int lans11 =0, rans11 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans11+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans11+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans11 += lmn, rans11+=rmn;
	}

	sort(robs.rbegin(), robs.rend(), cmp2);
	sort(srs.begin(), srs.end(), cmp2);
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int lans22 =0, rans22 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans22+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans22+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}
			else rmn = max(rmn, rdif);
		}
		lans22 += lmn, rans22+=rmn;
	}
	int final_ans = min(min(lans11+rans11, lans22+rans22), min(lans+rans, lans2+rans2));
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(llp a, llp b)
{
	return a.first<b.first;
}

bool cmp2(llp a, llp b)
{
	return a.second<b.second;
}

void input_fun()
{
	ll rob, sr;
	cin>>rob>>sr;
	vector<llp> robs(rob), srs(sr);
	for(ll i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(ll i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	ll mxl=0,mxr=0;
	for(ll i=0;i<rob;i++){
		for(ll j=0;j<sr;j++){
			ll ldif = max(0LL, srs[j].first - robs[i].first+1);
			ll rdif = max(0LL, srs[j].second-robs[i].second+1);
			if(ldif < rdif){
				mxl = max(mxl, ldif);
			}
			else if(ldif == rdif){
				mxl = max(mxl, ldif);
				mxr = max(mxr, rdif);
			}
			else mxr = max(mxr, rdif);
		}
	}
	sort(robs.begin(), robs.end(), cmp1);
	sort(srs.rbegin(), srs.rend(), cmp1);
	ll lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		ll lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			ll ldif = max(0LL, srs[j].first - robs[i].first-lans+1);
			ll rdif = max(0LL, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	ll lans11 =0, rans11 = 0;
	for(int i=0;i<rob;i++){
		ll lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			ll ldif = max(0LL, srs[j].first - robs[i].first-lans11+1);
			ll rdif = max(0LL, srs[j].second-robs[i].second-rans11+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans11 += lmn, rans11+=rmn;
	}

	sort(robs.begin(), robs.end(), cmp2);
	sort(srs.rbegin(), srs.rend(), cmp2);
	ll lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		ll lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			ll ldif = max(0LL, srs[j].first - robs[i].first-lans2+1);
			ll rdif = max(0LL, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	ll lans22 =0, rans22 = 0;
	for(int i=0;i<rob;i++){
		ll lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			ll ldif = max(0LL, srs[j].first - robs[i].first-lans22+1);
			ll rdif = max(0LL, srs[j].second-robs[i].second-rans22+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans22 += lmn, rans22+=rmn;
	}
	ll final_ans = min(min(lans11+rans11, lans22+rans22), min(lans+rans, lans2+rans2));
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}


//**********************************### With The name of Allah ###***********************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;
// All unique value
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set1;
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
typedef tree<pair<int, int>, null_type, less<pair<int,int> >,rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// Policy End
// Modular inverse short.
long long inv(long long a, long long md){ return 1<a ? md - inv(md%a,a)*md/a : 1; }
// random generator. Very useful.
mt19937_64 my_rand(std::random_device{}());
ll rnd(ll x){return my_rand()%x;}
// Binary Indexted Tree, Again, very useful.	Note: BIT is always indexed from 1 to n, not from 0.
vector<ll> BIT_array;	//Need to resize with required size
// Update value at index i. Here mx should be equal to BIT_array size.
void upd_BIT(int i,ll val, ll mx){for(;i<mx;i+=(i&-i))BIT_array[i]+=val;}
// This returns the sum of values from index 1 to i.
ll sum_BIT(int i){ll res=0;for(;i>0;i-=(i&-i))res+=BIT_array[i];return res;}
// This will return the first position where sum from 0 to pos is not less then s. We can also return the last position where sum less then s. For that return pos insted of pos+1.
ll pos_where_sum_not_less_then_s_BIT(ll s, ll mx){ll pos=0,sum=0;for(ll i=20;i>=0;i--)if(pos+(1<<i)<mx&&sum+BIT_array[pos+(1<<i)]<s)sum+=BIT_array[pos+(1<<i)],pos+=1<<i;return pos+1;}
#define PI atan(1)*4
#define iip pair<int,int>
#define llp pair<ll,ll>
#define MX 2009

bool cmp1(iip a, iip b)
{
	return a.first<b.first;
}

bool cmp2(iip a, iip b)
{
	return a.second<b.second;
}

void input_fun()
{
	int rob, sr;
	cin>>rob>>sr;
	vector<iip> robs(rob), srs(sr);
	for(int i=0;i<rob;i++)cin>>robs[i].first>>robs[i].second;
	for(int i=0;i<sr;i++)cin>>srs[i].first>>srs[i].second;
	if(rob == 0 || sr == 0){
		cout<<0<<endl;
		return;
	}
	int mxl=0,mxr=0;
	for(int i=0;i<rob;i++){
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first+1);
			int rdif = max(0, srs[j].second-robs[i].second+1);
			if(ldif < rdif){
				mxl = max(mxl, ldif);
			}
			else mxr = max(mxr, rdif);
		}
	}
	sort(robs.rbegin(), robs.rend(), cmp1);
	sort(srs.begin(), srs.end(), cmp1);
	int lans =0, rans = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}
			else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans += lmn, rans+=rmn;
	}
	int lans11 =0, rans11 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans11+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans11+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans11 += lmn, rans11+=rmn;
	}

	sort(robs.rbegin(), robs.rend(), cmp2);
	sort(srs.begin(), srs.end(), cmp2);
	int lans2 =0, rans2 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans2+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans2+1);
			if(ldif < rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans2 += lmn, rans2+=rmn;
	}
	int lans22 =0, rans22 = 0;
	for(int i=0;i<rob;i++){
		int lmn = 0, rmn = 0;
		for(int j=0;j<sr;j++){
			int ldif = max(0, srs[j].first - robs[i].first-lans22+1);
			int rdif = max(0, srs[j].second-robs[i].second-rans22+1);
			if(ldif <= rdif){
				lmn = max(lmn, ldif);
			}else if(ldif == rdif){
				if(lans+ldif<=mxl)lmn=max(lmn, ldif);
				else rmn = max(rmn, rdif);
			}
			else rmn = max(rmn, rdif);
		}
		lans22 += lmn, rans22+=rmn;
	}
	int final_ans = min(min(lans11+rans11, lans22+rans22), min(lans+rans, lans2+rans2));
	cout<<final_ans<<endl;
}

int main()
{
	//freopen("/home/shajal/Desktop/input.txt", "r+", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);

    input_fun();
return 0;
}