#include <bits/stdc++.h>
using namespace std;
inline int read() {
  register int x = 0, f = 1;
  register char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = 0;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + (ch ^ '0');
    ch = getchar();
  }
  return f ? x : -x;
}
int n, m, yt, Y[200005];
struct subway {
  int x, y;
} sbw[100005];
struct rabbit {
  int x, y, dis;
} rbt[100005];
struct BIT {
  int tr[200005];
  void modify(int x, int v) {
    for (; x <= yt; x += x & -x) tr[x] = max(tr[x], v);
  }
  int query(int x) {
    int ans = -1000000000;
    for (; x; x -= x & -x) ans = max(ans, tr[x]);
    return ans;
  }
} bit;
struct node {
  int x, y, id;
} q[200005];
void work() {
  memset(bit.tr, -0x3f, sizeof bit.tr);
  yt = 0;
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    Y[++yt] = rbt[i].y;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    Y[++yt] = sbw[i].y;
  }
  sort(Y + 1, Y + yt + 1), yt = unique(Y + 1, Y + yt + 1) - Y - 1;
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i)
    q[i] = (node){rbt[i].x, rbt[i].y, i};
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i)
    q[n + i] = (node){sbw[i].x, sbw[i].y, n + i};
  sort(q + 1, q + n + m + 1,
       [&](node a, node b) { return a.x == b.x ? a.id > b.id : a.x < b.x; });
  for (int i = (1), _ed_ = (n + m); i <= _ed_; ++i) {
    if (q[i].id > n)
      bit.modify(lower_bound(Y + 1, Y + yt + 1, q[i].y) - Y, q[i].x + q[i].y);
    else
      rbt[q[i].id].dis =
          min(rbt[q[i].id].dis,
              q[i].x + q[i].y -
                  bit.query(lower_bound(Y + 1, Y + yt + 1, q[i].y) - Y));
  }
}
int rt[100005], tcnt, tr[6000005], ls[6000005], rs[6000005];
void pushup(int p) { tr[p] = tr[ls[p]] + tr[rs[p]]; }
void insert(int& x, int y, int l, int r, int pos) {
  x = ++tcnt;
  tr[x] = tr[y], ls[x] = ls[y], rs[x] = rs[y];
  if (l == r) return ++tr[x], void();
  int mid = (l + r) >> 1;
  if (pos <= mid)
    insert(ls[x], ls[y], l, mid, pos);
  else
    insert(rs[x], rs[y], mid + 1, r, pos);
  pushup(x);
}
int query(int x, int y, int l, int r, int L, int R) {
  if (L > R || x == y) return 0;
  if (L <= l && r <= R) return tr[x] - tr[y];
  int mid = (l + r) >> 1, ans = 0;
  if (L <= mid) ans += query(ls[x], ls[y], l, mid, L, R);
  if (ans) return ans;
  if (mid < R) ans += query(rs[x], rs[y], mid + 1, r, L, R);
  return ans;
}
int lower(int x) {
  int l = 1, r = m, ans = r + 1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (sbw[mid].x >= x)
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  return ans;
}
int upper(int x) {
  int l = 1, r = m, ans = r + 1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (sbw[mid].x > x)
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  return ans - 1;
}
int query(int x, int y) {
  int l = 0, r = 1000000000, ans, L, R, D, U;
  while (l <= r) {
    int mid = (l + r) >> 1;
    L = lower(x - mid), R = upper(x + mid),
    D = lower_bound(Y + 1, Y + yt + 1, y - mid) - Y,
    U = upper_bound(Y + 1, Y + yt + 1, y + mid) - Y - 1;
    if (L <= R && query(rt[R], rt[L - 1], 1, yt, D, U))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  return ans;
}
struct square {
  int x1, y1, x2, y2;
  square(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0)
      : x1(x1), y1(y1), x2(x2), y2(y2) {}
  void merge(square o) {
    x1 = max(x1, o.x1), y1 = max(y1, o.y1);
    x2 = min(x2, o.x2), y2 = min(y2, o.y2);
  }
  bool valid() {
    if (x1 == x2 && y1 == y2 && (x1 + y1) & 1) return 0;
    return x1 <= x2 && y1 <= y2;
  }
};
bool check(int tim) {
  int p = n;
  while (p && rbt[p].dis > tim) --p;
  square nw(-1000000000, -1000000000, 1000000000, 1000000000);
  for (int i = (n), _ed_ = (p + 1); i >= _ed_; --i)
    nw.merge(
        square(rbt[i].x - tim, rbt[i].y - tim, rbt[i].x + tim, rbt[i].y + tim));
  int L, R, D, U;
  while (p && nw.valid()) {
    int t = tim - rbt[p].dis, x1 = nw.x1, y1 = nw.y1, x2 = nw.x2, y2 = nw.y2;
    if (x1 == x2) {
      if ((x1 + y1) & 1) ++y1;
      if ((x2 + y2) & 1) --y2;
    } else if (y1 == y2) {
      if ((x1 + y1) & 1) ++x1;
      if ((x2 + y2) & 1) --x2;
    }
    if (x1 <= x2 && y1 <= y2) {
      L = lower(x1 - t), R = upper(x2 + t),
      D = lower_bound(Y + 1, Y + yt + 1, y1 - t) - Y,
      U = upper_bound(Y + 1, Y + yt + 1, y2 + t) - Y - 1;
      if (L <= R && query(rt[R], rt[L - 1], 1, yt, D, U)) return 1;
    }
    nw.merge(
        square(rbt[p].x - tim, rbt[p].y - tim, rbt[p].x + tim, rbt[p].y + tim));
    --p;
  }
  if (nw.valid()) return 1;
  return 0;
}
int main() {
  n = read(), m = read();
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i)
    rbt[i] = (rabbit){read(), read(), 1000000000};
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i)
    sbw[i] = (subway){read(), read()};
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    rbt[i].x *= -1;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    sbw[i].x *= -1;
  }
  work();
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    rbt[i].y *= -1;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    sbw[i].y *= -1;
  }
  work();
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    rbt[i].x *= -1;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    sbw[i].x *= -1;
  }
  work();
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    rbt[i].y *= -1;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    sbw[i].y *= -1;
  }
  work();
  for (int i = (1), _ed_ = (n); i <= _ed_; ++i) {
    int x = rbt[i].x, y = rbt[i].y;
    rbt[i].x = x + y, rbt[i].y = x - y;
  }
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) {
    int x = sbw[i].x, y = sbw[i].y;
    sbw[i].x = x + y, sbw[i].y = x - y;
  }
  sort(sbw + 1, sbw + m + 1,
       [&](subway a, subway b) { return a.x == b.x ? a.y < b.y : a.x < b.x; });
  yt = 0;
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i) Y[++yt] = sbw[i].y;
  sort(Y + 1, Y + yt + 1), yt = unique(Y + 1, Y + yt + 1) - Y - 1;
  for (int i = (1), _ed_ = (m); i <= _ed_; ++i)
    insert(rt[i], rt[i - 1], 1, yt,
           lower_bound(Y + 1, Y + yt + 1, sbw[i].y) - Y);
  sort(rbt + 1, rbt + n + 1, [&](rabbit a, rabbit b) { return a.dis < b.dis; });
  int l = 0, r = rbt[n].dis, ans;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (check(mid))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  printf("%d\n", ans);
  return 0;
}
