//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <complex>
#include <iomanip>
#include <iostream>
#include <limits>
#include <inttypes.h>
#include <map>
#include <math.h>
#include <memory>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = int64_t;
using ull = uint64_t;

[[maybe_unused]] constexpr ll LL_MAX = numeric_limits<ll>::max();
[[maybe_unused]] constexpr ll LL_MIN = numeric_limits<ll>::min();
[[maybe_unused]] constexpr ull ULL_MAX = numeric_limits<ull>::max();

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

template<typename T>
void chmin(T& x, T y) {
	x = min(x, y);
}

template<typename T>
void chmax(T& x, T y) {
	x = max(x, y);
}

ll csum(ll x, ll y) {
	if (x > 0 && y > 0 && x > LL_MAX - y) {
		return LL_MAX;
	}
	if (x < 0 && y < 0 && x < LL_MIN - y) {
		return LL_MIN;
	}
	return x + y;
}

ll readi() {
	ll ret;
	scanf("%" PRId64 "", &ret);
	return ret;
}

vector<ll> readvi(ll n) {
	vector<ll> ret(n);
	rep(i, 0, n) { ret[i] = readi(); }
	return ret;
}

string reads() {
    string s;
    cin >> s;
    return s;
}

void writei(ll x) {
	printf("%" PRId64 "\n", x);
}

void writevi(const vector<ll>& xs) {
    rep(i,0,xs.size()) {
        if (i < xs.size() - 1) {
            printf("%" PRId64 " ", xs[i]);
        } else {
            printf("%" PRId64 "\n", xs[i]);
        }
    }
}

template<typename T>
vector<T> make_vec_nd(T init, ll size) {
	return vector<T>(size, init);
}
template<typename T, typename... Args>
auto make_vec_nd(T init, ll size, Args... rest) {
	auto inner = make_vec_nd(init, rest...);
	return vector<decltype(inner)>(size, inner);
}

template<typename Monoid>
struct SegmentTree {
    using Op = function<Monoid(const Monoid& lhs, const Monoid& rhs)>;
    ll width;
    vector<Monoid> node;
    Op op;
    Monoid unit;
    
    SegmentTree(ll N, Op op, Monoid unit)
    : SegmentTree(vector<Monoid>(N, unit), op, unit) {}
    SegmentTree(const vector<Monoid>& elems, Op op, Monoid unit)
    : op(op)
    , unit(unit) {
        width = 1;
        while (width < elems.size()) {
            width *= 2;
        }
        node.resize(2 * width - 1, unit);
        for (size_t i = 0; i < elems.size(); i++) {
            node[i + width - 1] = elems[i];
        }
        for (size_t i = width - 2; i != numeric_limits<size_t>::max(); i--) {
            node[i] = op(node[2 * i + 1], node[2 * i + 2]);
        }
    }
    void update(ll idx, Monoid elem) {
        idx += width - 1;
        node[idx] = elem;
        while (idx >= 1) {
            idx = (idx - 1) / 2;
            node[idx] = op(node[2 * idx + 1], node[2 * idx + 2]);
        }
    }
    Monoid query_core(ll a, ll b, ll root, ll left, ll right) const {
        // assert([left, right) = root以下にある範囲)
        assert(0 <= a && b <= width);
        if (right <= a || b <= left) {
            return unit;
        }
        if (a <= left && right <= b) {
            return node[root];
        }
        ll mid = (left + right) / 2;
        Monoid ans_l = query_core(a, b, 2 * root + 1, left, mid);
        Monoid ans_r = query_core(a, b, 2 * root + 2, mid, right);
        return op(ans_l, ans_r);
    }
    Monoid query(ll a, ll b) const {
        assert(0 <= a && b <= width);
        return query_core(a, b, 0, 0, width);
    }
    Monoid operator[](size_t idx) { return query(idx, idx + 1); }
};

int main() {
    ll H = readi();
    ll W = readi();
    ll M = readi();
    vector<ll> cnt_x(W);
    vector<ll> cnt_y(H);
    vector<unordered_set<ll>> x_list(H);
    rep(i,0,M) {
        ll y = readi();
        ll x = readi();
        x--;
        y--;
        cnt_x[x]++;
        cnt_y[y]++;
        x_list[y].insert(x);
    }
    SegmentTree<ll> tree(cnt_x, [](ll lhs, ll rhs){ return max(lhs, rhs); }, LL_MIN);
    ll ans = LL_MIN;
    rep(y,0,H) {
        for (ll x : x_list[y]) {
            tree.update(x, tree[x] - 1);
        }
        chmax(ans, cnt_y[y] + tree.query(0, W));
        for (ll x : x_list[y]) {
            tree.update(x, tree[x] + 1);
        }
    }
    writei(ans);
}


Measured memory_bytes: 46240