#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)n; ++i)
#define rrep(i, n) for (int i = (int)n-1; i >= 0; --i)
using namespace std;
using ll = long long;
template<typename T>
inline bool chmax(T& a, const T& b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
template<typename T>
inline bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}
template<typename T> vector<T> make_vec(size_t n) { return vector<T>(n); }
template<typename T, typename... Args> auto make_vec(size_t n, Args... args) {
    return vector<decltype(make_vec<T>(args...))>(n, make_vec<T>(args...));
}
template<typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value>::type fill_v(U& u, const V... v) { u = U(v...); }
template<typename T, typename U, typename... V>
typename enable_if<!is_same<T, U>::value>::type fill_v(U& u, const V... v) {
    for (auto& e : u) fill_v<T>(e, v...);
}

template <typename T>
struct segment_tree {
    using F = function<T(T, T)>;
    int n;
    vector<T> data;
    F operation;
    T identity;
    segment_tree(F operation, T identity)
        : operation(operation), identity(identity) {}
    void init(int n_) {
        n = 1;
        while (n < n_) n <<= 1;
        data.assign(n<<1, identity);
    }
    void build(const vector<T> &v) {
        int n_ = (int)v.size();
        init(n_);
        for (int i = 0; i < n_; ++i) data[n+i] = v[i];
        for (int i = n-1; i >= 1; --i) {
            data[i] = operation(data[i<<1|0], data[i<<1|1]);
        }
    }
    T operator[](int i) { return data[n+i];}
    void set(int i, T x) {
        i += n;
        data[i] = x;
        while (i > 1) {
            i >>= 1;
            data[i] = operation(data[i<<1|0], data[i<<1|1]);
        }
    }
    T fold(int l, int r) {
        l += n; r += n;
        T resl = identity, resr = identity;
        while (l < r) {
            if (l & 1) resl = operation(resl, data[l++]);
            if (r & 1) resr = operation(data[--r], resr);
            l >>= 1; r >>= 1;
        }
        return operation(resl, resr);
    }
    template <typename C>
    int find(int st, C &check, T &acc, int i, int l, int r) {
        if (l+1 == r) {
            acc = operation(acc, data[i]);
            return check(acc) ? i-n : -1;
        }
        int m = (l+r)>>1;
        if (m <= st) return find(st, check, acc, i<<1|1, m, r);
        if (st <= l && !check(operation(acc, data[i]))) {
            acc = operation(acc, data[i]);
            return -1;
        }
        int vl = find(st, check, acc, i<<1|0, l, m);
        if (vl != -1) return vl;
        return find(st, check, acc, i<<1|1, m, r);
    }
    // min idx s.t. st <= idx && !check(fold(st, idx-1)) && check(fold(st, idx))
    template <typename C>
    int find(int st, C &check) {
        T acc = identity;
        return find(st, check, identity, 1, 0, n);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int h, w, m;
    cin >> h >> w >> m;

    auto js = make_vec<int>(h, 0);
    vector<int> colsum(w);
    rep(i, m) {
        int y, x;
        cin >> y >> x;
        y--; x--;
        js[y].push_back(x);
        colsum[x]++;
    }

    auto f = [](int a, int b) { return max(a, b); };
    segment_tree<int> seg(f, 0);
    seg.build(colsum);

    int ans = 0;
    rep(i, h) {
        for (auto j : js[i]) {
            seg.set(j, seg[j] - 1);
        }
        int now = js[i].size();
        now += seg.fold(0, w);
        chmax(ans, now);
        for (auto j : js[i]) {
            seg.set(j, seg[j] + 1);
        }
    }
    cout << ans << '\n';
}


Measured memory_bytes: 24812