#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<string.h>

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define NDEBUG
#define eprintf(...) do {} while (0)
#endif
#include<cassert>

using namespace std;

typedef long long LL;
typedef vector<int> VI;

#define REP(i,n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(),i##_end=(c).end();i!=i##_end;++i)

template<class T> inline void amin(T &x, const T &y) { if (y<x) x=y; }
template<class T> inline void amax(T &x, const T &y) { if (x<y) x=y; }
#define rprintf(fmt, begin, end) do { const auto end_rp = (end); auto it_rp = (begin); for (bool sp_rp=0; it_rp!=end_rp; ++it_rp) { if (sp_rp) putchar(' '); else sp_rp = true; printf(fmt, *it_rp); } putchar('\n'); } while(0)
template<class T> struct Fenwick {
    int n;
    T* d;
    Fenwick() : n(0), d(NULL) {}
    Fenwick(int n_) : n(n_) {
	d = new T[n_]();
    }
    Fenwick(const Fenwick &y) : n(y.n) {
	d = new T[n];
	memcpy(d, y.d, sizeof (T) * n);
    }
    ~Fenwick() {
	delete[] d; d = NULL;
	n = 0;
    }
    friend void swap(Fenwick &x, Fenwick &y) {
	swap(x.n, y.n); swap(x.d, y.d);
    }
    Fenwick& operator=(Fenwick y) {
	swap(*this, y);
	return *this;
    }
    inline void add(int i, const T &x) {
	for (; i<n; i|=i+1) d[i] += x;
    }
    inline T sum(int r) const {
	T s = T();
	for (; r; r&=r-1) s += d[r-1];
	return s;
    }
    T sum(int l, int r) const {
	return sum(r) - sum(l);
    }
    int lower_bound(const T &x) const { // sum(ret) < x <= sum(ret+1);
	if (n == 0) return 0;
	int i = 0; T s = T();
	for (int k=1<<__lg(n); k; k>>=1) {
	    if (i+k <= n && s + d[i+k-1] < x) {
		i += k; s += d[i-1];
	    }
	}
	return i;
    }
    int upper_bound(const T &x) const { // sum(ret) <= x < sum(ret+1);
	if (n == 0) return 0;
	int i = 0; T s = T();
	for (int k=1<<__lg(n); k; k>>=1) {
	    if (i+k <= n && !(x < s + d[i+k-1])) {
		i += k; s += d[i-1];
	    }
	}
	return i;
    }
};

int H, W, M;
int R[200011], C[200011];
int idx[200011];
bool use[200011];
bool act[200011];

void MAIN() {
    scanf("%d%d%d", &H, &W, &M);
    REP (i, M) scanf("%d%d", R+i, C+i), R[i]--, C[i]--;

    LL ans = 0;
    if (M == 0) {
	ans = (LL) H * W;
    } else {
	int minR = H;
	int minC = W;
	REP (i, M) {
	    if (R[i] == 0) amin(minC, C[i]);
	    if (C[i] == 0) amin(minR, R[i]);
	}

	ans += (LL)H * W;
	ans -= W - minC;
	ans -= H - minR;

	REP (i, M) idx[i] = i;
	sort(idx, idx + M, [&](int i, int j) {
		return C[i] < C[j];
		});

	for (int i=minR; i<H; i++) use[i] = true;

	REP (i, M) {
	    if (!use[R[idx[i]]]) {
		use[R[idx[i]]] = true;
		act[idx[i]] = true;
	    }
	}

	Fenwick<LL> F(H+11);

	LL bad = 0;
	int p = M-1;
	for (int i=W-1; i>0; i--) {
	    int nxt = H;

	    int q = p;
	    while (q >= 0 && C[idx[q]] == i) {
		q--;
	    }

	    for (int k=p; k>q; k--) {
		int r = R[idx[k]];
		int c = C[idx[k]];
		amin(nxt, r);
	    }

	    if (minC <= i) nxt= 0;
	    F.add(nxt, 1);

	    for (int k=p; k>q; k--) {
		int r = R[idx[k]];
		int c = C[idx[k]];

		// [c, Right[r]);
		if (r != 0 && act[idx[k]]) {
		    bad += F.sum(0, r+1);
		}
	    }

	    p = q;
	}

	for (int i=minR; i<H; i++) {
	    bad += F.sum(0, i+1);
	}

	ans -= bad;
    }
    printf("%lld\n", ans);

}

int main() {
    int TC = 1;
//    scanf("%d", &TC);
    REP (tc, TC) MAIN();
    return 0;
}


#include <vector>

template <typename T, typename F>
class segment_tree {
public:
	segment_tree(int n, const F& f, const T& e)
		: f(f), e(e)
	{
		sz = 1;
		while (sz < n) {
			sz *= 2;
		}
		dat.assign(2 * sz, e);
	}

	void update(int i, const T& x) {
		i += sz;
		dat[i] = x;
		while (i > 1) {
			i /= 2;
			dat[i] = f(dat[2 * i + 0], dat[2 * i + 1]);
		}
	}

	T query(int i) const {
		return dat[i + sz - 1];
	}

	T query(int a, int b) const {
		T l = e;
		T r = e;
		a += sz;
		b += sz;
		for (; a < b; a /= 2, b /= 2) {
			if (a & 1) {
				l = f(l, dat[a]);
				++a;
			}
			if (b & 1) {
				--b;
				r = f(dat[b], r);
			}
		}
		return f(l, r);
	}

private:
	F f;
	T e;
	int sz;
	std::vector<T> dat;
};

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	int H, W, M;
	cin >> H >> W >> M;
	vector<int> X(M), Y(M);
	for (int k = 0; k < M; ++k) {
		cin >> X[k] >> Y[k];
		--X[k];
		--Y[k];
	}

	vector<vector<int>> o_cols(H);
	vector<vector<int>> o_rows(W);

	for (int k = 0; k < M; ++k) {
		o_cols[X[k]].push_back(Y[k]);
		o_rows[Y[k]].push_back(X[k]);
	}

	for (int i = 0; i < H; ++i) {
		sort(o_cols[i].begin(), o_cols[i].end());
	}
	for (int j = 0; j < W; ++j) {
		sort(o_rows[j].begin(), o_rows[j].end());
	}

	if (!o_cols[0].empty()) {
		int leftmost = o_cols[0][0];
		for (int col = leftmost + 1; col < W; ++col) {
			o_cols[0].push_back(col);
		}
		sort(o_cols[0].begin(), o_cols[0].end());
		o_cols[0].erase(unique(o_cols[0].begin(), o_cols[0].end()), o_cols[0].end());
	}

	long long ans = 0;

	int j_max = o_cols[0].empty() ? W : o_cols[0][0];
	for (int j = 0; j < j_max; ++j) {
		int upmost = o_rows[j].empty() ? H : o_rows[j][0];
		ans += upmost;
	}

	// range sum query
	auto f = [](int a, int b) { return a + b; };
	auto e = 0;
	segment_tree<int, decltype(f)> seg(W, f, e);

	int i_max = o_rows[0].empty() ? H : o_rows[0][0];
	for (int i = 1; i < i_max; ++i) {
		for (auto& col : o_cols[i - 1]) {
			seg.update(col, 1);
		}
		int leftmost = o_cols[i].empty() ? W : o_cols[i][0];
		ans += seg.query(0, leftmost);
	}

	cout << ans << endl;
}
