unittest
{
	assert( [ "2 3 3", "2 2", "1 1", "1 3" ].solve == 3 );
	assert( [ "3 3 4", "3 3", "3 1", "1 1", "1 2" ].solve == 3 );
	assert( [ "5 5 10", "2 5", "4 3", "2 3", "5 5", "2 2", "5 4", "5 3", "5 1", "3 5", "1 4" ].solve == 6 );
}



import std.algorithm;
import std.container;
import std.conv;
import std.format;
import std.range;
import std.stdio;

void main()
{
	stdin.byLineCopy.solve.writeln;
}

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto h = 0L;
	auto w = 0L;
	auto m = 0L;
	input.front.formattedRead!"%s %s %s"( h, w, m );
	auto hws = new long[ 2 ][ m ];
	foreach( ref hw; hws )
	{
		input.popFront;
		hw = input.front.split.to!( long[] );
		hw[] -= 1;
	}
	
	auto pss = new long[][ h ];
	auto yts = new long[ w ];
	auto xts = new long[ h ];
	foreach( hw; hws )
	{
		pss[ hw[ 0 ] ] ~= hw[ 1 ];
		yts[ hw[ 1 ] ]++;
		xts[ hw[ 0 ] ]++;
	}
	
	auto ans = 0L;
	auto rbt = redBlackTree!( true, long )( yts );
	foreach( y, xt, ps; lockstep( xts, pss ) )
	{
		foreach( p; ps )
		{
			rbt.removeKey( yts[ p ] );
			rbt.insert( yts[ p ] - 1 );
		}
		ans = max( ans, xt + rbt.back );
		foreach( p; ps )
		{
			rbt.removeKey( yts[ p ] - 1 );
			rbt.insert( yts[ p ] );
		}
	}
	return ans;
}
