#pragma once
#undef _GLIBCXX_DEBUG

#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                      { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif // ONLINE_JUDGE

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <typename T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <typename T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <typename T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define ld              long double
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define sz(a)           (int)(a.size())
#define ook             order_of_key             // The number of items in a set that are strictly smaller than k
#define fbo             find_by_order            // It returns an iterator to the i'th largest element
#define ATCODER         if (fopen("in.txt", "r")) { freopen("in.txt", "r", stdin); }

//#define int             long long int

const int maxn = 1000000 + 5;
const int logn = 19;
const long long MOD = 1e9 + 7;
const long long INF = 1e18;

template <typename T>
struct Node {
      T sum;
      T maxi;
      T mini;
      bool toset;
      bool toadd;
      T lazy;
      Node(T sum = 0, T maxi = numeric_limits <T>::min(), T mini = numeric_limits <T>::max(),
           bool toset = 0, bool toadd = 0, T lazy = 0)
           : sum(sum), maxi(maxi), mini(mini), toset(toset), toadd(toadd), lazy(lazy) {}
};

ll arr[maxn];

template <typename T>
struct SegmentTree {
      #define Node             Node <T>
      #define lchild           node * 2
      #define rchild           node * 2 + 1
      #define mid              (int)(a + b) / 2

      int n;
      vector <Node> st;

      void init(int N) {
            n = N;
            st.clear();
            st.resize(4 * N + 5);
      }
      void marge(int node, int a, int b) {
            st[node].sum = st[lchild].sum + st[rchild].sum;
            st[node].maxi = max(st[lchild].maxi, st[rchild].maxi);
            st[node].mini = min(st[lchild].mini, st[rchild].mini);
      }
      void build(int node, int a, int b) {
            if (a == b) {
                  int val = arr[a];
                  st[node].sum = val;
                  st[node].maxi = val;
                  st[node].mini = val;
                  return;
            }
            build(lchild, a, mid);
            build(rchild, mid + 1, b);
            marge(node, a, b);
      }
      void propagate1(int node, int a, int b) {
            if (a != b) {
                  st[lchild].toset = st[rchild].toset = 1;
                  st[lchild].toadd = st[rchild].toadd = 0;
                  st[lchild].lazy = st[rchild].lazy = st[node].lazy;
            }
            st[node].maxi = st[node].mini = st[node].lazy;
            st[node].sum = 1LL * (b - a + 1) * st[node].lazy;
            st[node].toset = st[node].toadd = 0;
            st[node].lazy = 0;
      }
      void propagate2(int node, int a, int b) {
            if (a != b) {
                  st[lchild].toadd = st[rchild].toadd = 1;
                  st[lchild].lazy += st[node].lazy;
                  st[rchild].lazy += st[node].lazy;
            }
            st[node].sum += 1LL * (b - a + 1) * st[node].lazy;
            st[node].maxi += st[node].lazy;
            st[node].mini += st[node].lazy;
            st[node].toadd = st[node].toset = 0;
            st[node].lazy = 0;
      }
      void update(int node, int a, int b, int i, int j, T val, bool toset) {
            if (st[node].toset) {
                  propagate1(node, a, b);
            }
            if (st[node].lazy) {
                  propagate2(node, a, b);
            }
            if (a > j or b < i) {
                  return;
            }
            if (a >= i and b <= j) {
                  if (toset) {
                        st[node].toset = 1;
                        st[node].toadd = 0;
                        st[node].lazy = val;
                        propagate1(node, a, b);
                  }
                  else {
                        st[node].toset = 0;
                        st[node].toadd = 1;
                        st[node].lazy += val;
                        propagate2(node, a, b);
                  }
                  return;
            }
            update(lchild, a, mid, i, j, val, toset);
            update(rchild, mid + 1, b, i, j, val, toset);
            marge(node, a, b);
      }
      Node query(int node, int a, int b, int i, int j) {
            if (st[node].toset) {
                  propagate1(node, a, b);
            }
            if (st[node].toadd) {
                  propagate2(node, a, b);
            }
            if (a > j or b < i) {
                  return Node();
            }
            if (a >= i and b <= j) {
                  return st[node];
            }
            Node p = query(lchild, a, mid, i, j);
            Node q = query(rchild, mid + 1, b, i, j);
            Node res;
            res.sum = p.sum + q.sum;
            res.maxi = max(p.maxi, q.maxi);
            res.mini = min(p.mini, q.mini);
            marge(node, a, b);
            return res;
      }
      void build() {
            build(1, 1, n);
      }
      void uset(int l, int r, T val) {
            update(1, 1, n, l, r, val, 1);
      }
      void uadd(int l, int r, T val) {
            update(1, 1, n, l, r, val, 0);
      }
      Node query(int l, int r) {
            return query(1, 1, n, l, r);
      }
      T get_sum(int l, int r) {
            return query(l, r).sum;
      }
      T get_maxi(int l, int r) {
            return query(l, r).maxi;
      }
      T get_mini(int l, int r) {
            return query(l, r).mini;
      }

      #undef Node
      #undef lchild
      #undef rchild
      #undef mid
};

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr); cout.tie(nullptr);
      cout.precision(12);

      bool FILEIO = 0;
      if (FILEIO and fopen("in.txt", "r")) {
            freopen("in.txt", "r", stdin);
      }

      int n, m, q;
      cin >> n >> m >> q;
      vector < vector <int> > vec(m + 1);
      SegmentTree <int> st;
      st.init(n);
      st.uset(1, n, 0);
      for (int i = 1; i <= q; i++) {
            int r, c;
            cin >> r >> c;
            st.uadd(r, r, 1);
            vec[c].push_back(r);
      }
      int maxi = 0;
      for (int i = 1; i <= m; i++) {
            int sum = 0;
            for (int r : vec[i]) {
                  sum++;
                  st.uadd(r, r, -1);
            }
            int seg = st.get_maxi(1, n);
            sum += seg;
            MAX(maxi, sum);
            for (int r : vec[i]) {
                  st.uadd(r, r, 1);
            }
      }
      cout << maxi << endl;

}




Measured memory_bytes: 43052