#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <unordered_map>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double LD;
using namespace std;
const int INF = 2147483647;
const int INF2 = 0x3f3f3f3f;
const ll INF64 = 4e18;
const double INFD = 1e30;
const double EPS = 1e-10;
const long double PI = acosl(-1);
const int MOD = 1e9 + 7;
template <typename T>
inline T read() {
    T X = 0, w = 0;
    char ch = 0;
    while (!isdigit(ch)) {
        w |= ch == '-';
        ch = getchar();
    }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
const int MAXN = 300005;
const int MAXV = 60;
int n, m, k;
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, 1, 0, -1};
int dr2[8] = {1, 1, 1, -1, -1, -1, 0, 0};
int dc2[8] = {1, 0, -1, 1, 0, -1, 1, -1};
int CASE = 1;
struct Point {
    int r, c;
};
#define ls nodes[p << 1]
#define rs nodes[p << 1 | 1]
#define self nodes[p]
struct SegTree {
    struct Node {
        int tag;
        int sum, maxx;
    };
    Node nodes[MAXN << 2];
    void build(int l, int r, int p) {
        self.tag = 0;
        if (l == r) {
            self.sum = self.maxx = 0;
            return;
        }
        int mid = (l + r) / 2;
        build(l, mid, p << 1);
        build(mid + 1, r, p << 1 | 1);
        push_up(l, r, p);
    }

    inline void modify(int l, int r, int p, int f) {
        self.tag += nodes[f].tag;
        self.sum += (r - l + 1) * nodes[f].tag;
        self.maxx += nodes[f].tag;
    }

    inline void push_down(int l, int r, int p) {
        if (self.tag != 0) {
            int mid = (l + r) / 2;
            modify(l, mid, p << 1, p);
            modify(mid + 1, r, p << 1 | 1, p);
            self.tag = 0;
        }
    }
    inline void push_up(int l, int r, int p) {
        self.sum = ls.sum + rs.sum;
        self.maxx = max(ls.maxx, rs.maxx);
    }
    void update(int x, int y, int l, int r, int p, int v) {
        if (x <= l && y >= r) {
            self.tag += v;
            self.sum += (r - l + 1) * v;
            self.maxx += v;
            return;
        }
        push_down(l, r, p);
        int mid = (l + r) / 2;
        if (x <= mid) update(x, y, l, mid, p << 1, v);
        if (y > mid) update(x, y, mid + 1, r, p << 1 | 1, v);
        push_up(l, r, p);
    }
    int query(int x, int y, int l, int r, int p) {
        if (x <= l && y >= r) return self.maxx;
        int res = 0;
        push_down(l, r, p);
        int mid = (l + r) / 2;
        if (x <= mid) res = max(res, query(x, y, l, mid, p << 1));
        if (y > mid) res = max(res, query(x, y, mid + 1, r, p << 1 | 1));
        return res;
    }
};
SegTree tree;
vector<int> R[MAXN];
int main() {
#ifdef LOCALLL
    freopen("in", "r", stdin);
    freopen("out", "w", stdout);
#endif
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < k; i++) {
        int r = read<int>(), c = read<int>();
        R[r].push_back(c);
        tree.update(c, c, 1, m, 1, 1);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (auto pt : R[i]) {
            tree.update(pt, pt, 1, m, 1, -1);
        }
        int c = R[i].size();
        ans = max(ans, c + tree.query(1, m, 1, m, 1));
        for (auto pt : R[i]) {
            tree.update(pt, pt, 1, m, 1, 1);
        }
    }
    printf("%d\n", ans);
    return 0;
}

Measured memory_bytes: 32460