#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <typename t>
using V = vector<t>;
template <typename t>
void print(ostream& os, const t& a) {
  os << a << '\n';
}
template <typename t, typename... A>
void print(ostream& os, const t& a, A&&... b) {
  os << a << ' ';
  print(os, b...);
}
constexpr int INF = 1e9 + 1;
constexpr int MaxRes = 1e9;
struct Point {
  int x, y;
  Point(int x = -INF, int y = -INF) : x(x), y(y) {}
};
struct Ev {
  int x, lo, hi, val;
  Ev(int x, int lo, int hi, int val = 1) : x(x), lo(lo), hi(hi), val(val) {}
};
inline bool operator<(const Ev& mn, const Ev& wc) {
  return mn.x == wc.x ? mn.val > wc.val : mn.x < wc.x;
}
struct Node {
  int val, v;
  Node() : val(0), v(0) {}
};
int n, m, k, rozm = 1;
V<Ev> evs;
V<int> low;
V<Node> tree;
V<Point> ign;
inline void upd(int v) {
  if (tree[v].val > 0)
    tree[v].v = INF;
  else {
    if (v >= rozm)
      tree[v].v = v - rozm;
    else
      tree[v].v = min(tree[v << 1].v, tree[(v << 1) + 1].v);
  }
}
inline void insert(int lo, int hi, int co) {
  lo += rozm;
  hi += rozm;
  tree[lo].val += co;
  if (lo != hi) tree[hi].val += co;
  upd(lo);
  upd(hi);
  while ((lo >> 1) != (hi >> 1)) {
    if ((lo & 1) == 0) {
      tree[lo + 1].val += co;
      upd(lo + 1);
    }
    if ((hi & 1) == 1) {
      tree[hi - 1].val += co;
      upd(hi - 1);
    }
    upd(lo);
    upd(hi);
    lo >>= 1;
    hi >>= 1;
  }
  upd(lo);
  upd(hi);
  for (lo >>= 1; lo >= 1; lo >>= 1) upd(lo);
}
inline void process(const Ev& ev) {
  int lo = lower_bound(begin(low), end(low), ev.lo) - begin(low);
  int hi = lower_bound(begin(low), end(low), ev.hi) - begin(low);
  insert(lo, hi, ev.val);
}
inline pair<bool, Point> process() {
  low.clear();
  tree.clear();
  rozm = 1;
  low.push_back(1);
  low.push_back(m);
  for (auto& ev : evs) {
    low.push_back(ev.lo);
    low.push_back(ev.hi);
  }
  sort(begin(low), end(low));
  low.resize(unique(begin(low), end(low)) - begin(low));
  int siz = low.size();
  for (int i = 0; i < siz - 1; ++i)
    if (low[i + 1] - low[i] > 1) low.push_back(low[i] + 1);
  sort(begin(low), end(low));
  while (rozm < low.size()) rozm <<= 1;
  tree.resize(rozm << 1);
  for (auto& n : tree) n = Node();
  for (int i = rozm; i < rozm << 1; ++i) tree[i].v = i - rozm;
  for (int i = rozm - 1; i >= 1; --i) upd(i);
  int pop = 1;
  int x = INT_MAX, y = INT_MAX;
  for (auto& ev : evs) {
    if (ev.x != pop) {
      if (tree[1].v < low.size()) {
        x = min(x, pop);
        y = min(y, low[tree[1].v]);
      }
      pop = ev.x;
    }
    process(ev);
  }
  if (tree[1].v < low.size()) {
    x = min(x, pop);
    y = min(y, low[tree[1].v]);
  }
  if (y == INT_MAX)
    return {true, Point()};
  else
    return {false, Point(x, y)};
}
inline void append_events(const Point& a, int v) {
  int lo = max(a.y - v, 1);
  int hi = min((ll)a.y + v, (ll)m);
  int d = max(a.x - v, 1);
  int u = min((ll)a.x + v + 1, (ll)n + 1);
  evs.emplace_back(d, lo, hi);
  if (u <= n) evs.emplace_back(u, lo, hi, -1);
}
inline bool check(int v) {
  ;
  evs.clear();
  for (auto& p : ign) append_events(p, v);
  sort(begin(evs), end(evs));
  ;
  bool res;
  Point q;
  tie(res, q) = process();
  if (res == true) {
    ;
    return true;
  };
  ;
  q.x += v;
  q.y += v;
  append_events(q, v);
  sort(begin(evs), end(evs));
  ;
  tie(res, q) = process();
  ;
  return res;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cin >> n >> m >> k;
  ign.resize(k);
  for (auto& p : ign) cin >> p.x >> p.y;
  int lo = -1;
  for (int b = MaxRes + 1; b >= 1; b >>= 1)
    while (lo + b <= MaxRes and check(lo + b) == false) lo += b;
  print(cout, lo + 1);
}
