//{{{
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset(a, b, sizeof(a))
#ifdef LOCAL
#include "prettyprint.hpp"
#endif
// clang-format off
void _print() { cerr << "]\033[0m\n"; }
template <typename T> void __print(T x) { cerr << x; }
template <typename T, typename... V> void _print(T t, V... v) { __print(t); if (sizeof...(v)) cerr << ", "; _print(v...); }
#ifdef LOCAL
#define debug(x...) cerr << "\033[1;34m[" << #x << "] = \033[1;32m["; _print(x)
#define debug_arr(x...) cerr << "\033[1;34m[" << #x << "] = \033[1;32m" << (x) << "\033[0m\n"
#else
#define debug(x...)
#define debug_arr(x...)
#endif
// clang-format on
//}}}

const int N = 3e5 + 10;
const int mod = 1e9 + 7;

const int inf = 0x3f3f3f3f;

int h, w, m;
int xx[N], yy[N];
int row_s[N];
int col_s[N];
set<pii> p;
vector<int> pp[N];

struct Node
{
    int max;  // sum
    LL lazy;  // add
} node[N << 2];

Node neutral;

#define lson(x) (x << 1)
#define rson(x) (x << 1 | 1)
struct segtree
{
    static const LL NO_OP = LLONG_MAX - 1;

    int sz;
    explicit segtree(int size) : sz(size)
    { /* TODO netual element for query merge */
        neutral.max = 0;
        neutral.lazy = NO_OP;
    }

    void pushup(Node& x, Node& lson, Node& rson) { x.max = max(lson.max, rson.max); }

    // [l, r) [lx, rx)
    void build(int x, int lx, int rx)
    {
        // assert(x >= 0);
        if (rx - lx == 1)
        {
            if (lx <= sz)
            {
                node[x].max = col_s[lx];
            }
            return;
        }

        node[x].lazy = NO_OP;

        int mid = (lx + rx) >> 1;
        build(lson(x), lx, mid);
        build(rson(x), mid, rx);

        pushup(node[x], node[lson(x)], node[rson(x)]);
        // debug(x, lx, rx, node[x].sum);
    }

    void modify(int x, int lx, int rx, int p, int v)
    {
        if (rx - lx == 1)
        {
            node[x].max += v;
            return;
        }

        int mid = (lx + rx) >> 1;
        if (p < mid)
            modify(lson(x), lx, mid, p, v);
        else
            modify(rson(x), mid, rx, p, v);

        pushup(node[x], node[lson(x)], node[rson(x)]);
    }

    int query(int x, int lx, int rx, int l, int r)
    {
        if (rx <= l || lx >= r) return -100;
        if (l <= lx && rx <= r) return node[x].max;

        int mid = (lx + rx) >> 1;
        int v1 = query(lson(x), lx, mid, l, r);
        int v2 = query(rson(x), mid, rx, l, r);
        return max(v1, v2);
    }
};

int main()
{
#ifdef LOCAL
    freopen("in", "r", stdin);
    // freopen("out", "w", stdout);
#endif

    while (cin >> h >> w >> m)
    {
        for (int i = 1; i <= h; i++) pp[i].clear();

        clr(row_s, 0);
        clr(col_s, 0);
        for (int i = 1; i <= m; ++i)
        {
            cin >> xx[i] >> yy[i];
            p.insert({xx[i], yy[i]});

            pp[xx[i]].push_back(yy[i]);

            row_s[xx[i]]++;
            col_s[yy[i]]++;
        }

        segtree tree(w + 1);
        tree.build(1, 1, w + 1);

        int ans = 0;
        for (int i = 1; i <= h; i++)
        {
            int cur = row_s[i];

            for (auto idx : pp[i]) tree.modify(1, 1, w + 1, idx, -1);

            int mx = tree.query(1, 1, w + 1, 1, w + 1);
            cur += mx;

            ans = max(cur, ans);

            for (auto idx : pp[i]) tree.modify(1, 1, w + 1, idx, 1);
        }
        cout << ans << endl;
    }

    return 0;
}


Measured memory_bytes: 55140