#include <bits/stdc++.h>
using namespace std;
template<typename T, typename U> T &ctmax(T &x, const U &y){ return x = max<T>(x, y); }
template<typename T, typename U> T &ctmin(T &x, const U &y){ return x = min<T>(x, y); }

// DEBUG BEGIN
#ifdef LOCAL
template<typename L, typename R> ostream &operator<<(ostream &out, const pair<L, R> &p){
	return out << "(" << p.first << ", " << p.second << ")";
}
template<typename Tuple, size_t N> struct TuplePrinter{
	static ostream &print(ostream &out, const Tuple &t){ return TuplePrinter<Tuple, N-1>::print(out, t) << ", " << get<N-1>(t); }
};
template<typename Tuple> struct TuplePrinter<Tuple, 1>{
	static ostream &print(ostream &out, const Tuple& t){ return out << get<0>(t); }
};
template<typename... Args> ostream &print_tuple(ostream &out, const tuple<Args...> &t){
	return TuplePrinter<decltype(t), sizeof...(Args)>::print(out << "(", t) << ")";
}
template<typename ...Args> ostream &operator<<(ostream &out, const tuple<Args...> &t){
	return print_tuple(out, t);
}
template<typename T> ostream &operator<<(enable_if_t<!is_same<T, string>::value, ostream> &out, const T &arr){
	out << "{"; for(auto &x: arr) out << x << ", ";
	return out << (arr.size() ? "\b\b" : "") << "}";
}
template<size_t S> ostream &operator<<(ostream &out, const bitset<S> &b){
	for(int i = 0; i < S; ++ i) out << b[i];
	return out;
}
void debug_out(){ cerr << "\b\b " << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){ cerr << H << ", ", debug_out(T...); }
void debug2_out(){ cerr << "-----DEBUG END-----\n"; }
template<typename Head, typename... Tail>
void debug2_out(Head H, Tail... T){ cerr << "\n"; for(auto x: H) cerr << x << "\n"; debug2_out(T...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__)
#define debug2(...) cerr << "----DEBUG BEGIN----\n[" << #__VA_ARGS__ << "]:", debug2_out(__VA_ARGS__)
#else
#define debug(...) 42
#define debug2(...) 42
#endif
// DEBUG END

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int h, w, m;
	cin >> h >> w >> m;
	vector<pair<vector<array<int, 2>>, int>> row(h), col(w);
	for(auto i = 0; i < h; ++ i){
		row[i].second = i;
	}
	for(auto j = 0; j < w; ++ j){
		col[j].second = j;
	}
	vector<array<int, 2>> a(m);
	for(auto i = 0; i < m; ++ i){
		int x, y;
		cin >> x >> y, -- x, -- y;
		a[i] = {x, y};
		row[x].first.push_back({x, y});
		col[y].first.push_back({x, y});
	}
	sort(a.begin(), a.end());
	for(auto i = 0; i < h; ++ i){
		sort(row[i].first.begin(), row[i].first.end());
	}
	for(auto j = 0; j < w; ++ j){
		sort(col[j].first.begin(), col[j].first.end());
	}
	sort(row.begin(), row.end(), [&](auto &p, auto &q){ return int(p.first.size()) > int(q.first.size()); }), sort(col.begin(), col.end(), [&](auto &p, auto &q){ return int(p.first.size()) > int(q.first.size()); });
	int ilow = 0, ihigh = 0, jlow = 0, jhigh = 0;
	vector<int> rflag(h), cflag(w);
	while(ihigh < h && int(row[ilow].first.size()) == int(row[ihigh].first.size())){
		rflag[row[ihigh].second] = true;
		++ ihigh;
	}
	while(jhigh < w && int(col[jlow].first.size()) == int(col[jhigh].first.size())){
		cflag[col[jhigh].second] = true;
		++ jhigh;
	}
	debug2(row);
	debug2(col);
	int res = int(row[ilow].first.size()) + int(col[jlow].first.size());
	a.erase(remove_if(a.begin(), a.end(), [&](auto p){ return !rflag[p[0]] || !cflag[p[1]]; }), a.end());
	debug(a);
	fill(rflag.begin(), rflag.end(), 0), fill(cflag.begin(), cflag.end(), 0);
	for(auto [x, y]: a){
		rflag[x] = cflag[y] = true;
	}
	cout << res - (int(a.size()) == 1LL * ihigh * jhigh) << "\n";
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////


Measured memory_bytes: 45400