Problem:
 Score : 500 points    Problem Statement We have a two-dimensional grid with H \times W squares. There are M targets to destroy in this grid - the position of the i -th target is \left(h_i, w_i \right) .  Takahashi will choose one square in this grid, place a bomb there, and ignite it. The bomb will destroy all targets that are in the row or the column where the bomb is placed. It is possible to place the bomb at a square with a target.  Takahashi is trying to maximize the number of targets to destroy. Find the maximum number of targets that can be destroyed.      Constraints  All values in input are integers.  1 \leq H, W \leq 3 \times 10^5  1 \leq M \leq \min\left(H\times W, 3 \times 10^5\right)  1 \leq h_i \leq H  1 \leq w_i \leq W  \left(h_i, w_i\right) \neq \left(h_j, w_j\right) \left(i \neq j\right)         Input Input is given from Standard Input in the following format:  H  W  M  h_1  w_1  \vdots  h_M  w_M       Output Print the answer.        Sample Input 1 2 3 3
2 2
1 1
1 3      Sample Output 1 3  We can destroy all the targets by placing the bomb at \left(1, 2\right) .       Sample Input 2 3 3 4
3 3
3 1
1 1
1 2      Sample Output 2 3       Sample Input 3 5 5 10
2 5
4 3
2 3
5 5
2 2
5 4
5 3
5 1
3 5
1 4      Sample Output 3 6

Solution (Python):
mod = 1000000007
eps = 10**-9


def main():
    import sys
    input = sys.stdin.readline

    H, W, M = map(int, input().split())
    cnt_h = [0] * (H+1)
    cnt_w = [0] * (W+1)
    B = set()
    for _ in range(M):
        h, w = map(int, input().split())
        cnt_h[h] += 1
        cnt_w[w] += 1
        B.add(h * (W+1) + w)

    hmax = max(cnt_h)
    wmax = max(cnt_w)
    h_list = []
    w_list = []
    for h in range(1, H+1):
        if cnt_h[h] == hmax:
            h_list.append(h)
    for w in range(1, W+1):
        if cnt_w[w] == wmax:
            w_list.append(w)
    if len(h_list) * len(w_list) > M:
        print(hmax + wmax)
    else:
        flg = 1
        for h in h_list:
            for w in w_list:
                if h * (W+1) + w not in B:
                    flg = 0
                    break
        print(hmax + wmax - flg)


if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


h,w,m = list(map(int, input().split()))
hw = []
hs = [0]*h
ws = [0]*w
for i in range(m):
    hh,ww = map(int, input().split())
    hh -= 1
    ww -= 1
    hw.append((hh,ww))
    hs[hh] += 1
    ws[ww] += 1

hs = [(v,i) for i,v in enumerate(hs)]
ws = [(v,i) for i,v in enumerate(ws)]
hs.sort(reverse=True)
ws.sort(reverse=True)
lh = set()
lw = set()
vh = hs[0][0]
vw = ws[0][0]
for i in range(h):
    if hs[i][0]!=vh:
        break
    else:
        lh.add(hs[i][1])
for i in range(w):
    if ws[i][0]!=vw:
        break
    else:
        lw.add(ws[i][1])
ans = vh + vw
val = len(lh)*len(lw)
for ih, iw in hw:
    if ih in lh and iw in lw:
        val -= 1
if val==0:
    ans -= 1
print(ans)

Solution (Python):
import sys
INF = 1 << 60
MOD = 10**9 + 7 
sys.setrecursionlimit(2147483647)
input = lambda:sys.stdin.readline().rstrip()

class SegmentTree(object):
    def __init__(self, A, dot, unit):
        n = 1 << (len(A) - 1).bit_length()
        tree = [unit] * (2 * n)
        for i, v in enumerate(A):
            tree[i + n] = v
        for i in range(n - 1, 0, -1):
            tree[i] = dot(tree[i << 1], tree[i << 1 | 1])
        self._n = n
        self._tree = tree
        self._dot = dot
        self._unit = unit

    def __getitem__(self, i):
        return self._tree[i + self._n]

    def update(self, i, v):
        i += self._n
        self._tree[i] = v
        while i != 1:
            i >>= 1
            self._tree[i] = self._dot(self._tree[i << 1], self._tree[i << 1 | 1])

    def add(self, i, v):
        self.update(i, self[i] + v)

    def sum(self, l, r):
        l += self._n
        r += self._n
        l_val = r_val = self._unit
        while l < r:
            if l & 1:
                l_val = self._dot(l_val, self._tree[l])
                l += 1
            if r & 1:
                r -= 1
                r_val = self._dot(self._tree[r], r_val)
            l >>= 1
            r >>= 1
        return self._dot(l_val, r_val)

def resolve():
    h, w, m = map(int, input().split())
    A = [[] for _ in range(h)]
    tree = SegmentTree([0] * w, max, 0)
    for _ in range(m):
        i, j = map(int, input().split())
        i -= 1; j -= 1
        A[i].append(j)
        tree.add(j, 1)

    ans = 0
    for i in range(h):
        for j in A[i]:
            tree.add(j, -1)
        ans = max(ans, len(A[i]) + tree.sum(0, w))
        for j in A[i]:
            tree.add(j, 1)

    print(ans)
resolve()

Solution (Python):
import sys
read = sys.stdin.buffer.read
readlines = sys.stdin.buffer.readlines
input = sys.stdin.buffer.readline
H, W, M = map(int, input().split())

HH = [0]*H
WW = [0]*W
d = set()
for line in readlines():
    h, w = map(int, line.split())
    h -= 1
    w -= 1
    d.add((h, w))
    HH[h] += 1
    WW[w] += 1

m = -1
argm = []
for i, c in enumerate(HH):
    if c > m:
        m = c
        argm = [i]
    elif c == m:
        argm.append(i)

mH = m
aH = argm

m = -1
argm = []
for i, c in enumerate(WW):
    if c > m:
        m = c
        argm = [i]
    elif c == m:
        argm.append(i)

mW = m
aW = argm

ans = mH + mW
for h in aH:
    for w in aW:
        if (h, w) not in d:
            break
    else:
        continue
    break
else:
    ans -= 1

print(ans)

Solution (Python):

import sys
from collections import deque, Counter
from heapq import heappop, heappush
from bisect import bisect_right
from itertools import accumulate

sys.setrecursionlimit(10**6)
INF = 10**12
m = 10**9 + 7

def main():
    H, W, M = map(int, input().split())
    h = [0] * H
    w = [0] * W
    hw = set()
    for i in range(M):
        tmph, tmpw = map(lambda x: int(x)-1, input().split())
        h[tmph] += 1
        w[tmpw] += 1
        hw.add((tmph,tmpw))
    
    HMAX = max(h)
    h0 = []
    for i in range(H):
        if h[i] == HMAX:
            h0.append(i)

    WMAX = max(w)
    w0 = []
    for i in range(W):
        if w[i] == WMAX:
            w0.append(i)

    ans = 0
    for i in h0:
        for j in w0:
            if (i,j) not in hw:
                print(HMAX+WMAX)
                exit()
    print(HMAX+WMAX-1)

if __name__ == "__main__":
    main()

Solution (Python):
import sys
def input():return sys.stdin.readline()[:-1]
def N(): return int(input())
def NM():return map(int,input().split())
def L():return list(NM())

H,W,m=NM()
import collections
hl=collections.defaultdict(int)
wl=collections.defaultdict(int)
hwl=set()
for i in range(m):
    h,w=NM()
    hl[h]+=1
    wl[w]+=1
    hwl.add((h,w))
mh=0
mw=0
mhl=[]
mwl=[]
for k,v in hl.items():
    if mh<v:
        mh=v
        mhl=[k]
    elif mh==v:
        mhl.append(k)
for k,v in wl.items():
    if mw<v:
        mw=v
        mwl=[k]
    elif mw==v:
        mwl.append(k)
if len(mhl)*len(mwl)>m:
    print(min(m,mh+mw))
else:
    for i in mhl:
        for j in mwl:
            if not (i,j) in hwl:
                print(min(m,mh+mw))
                quit()
    print(mh+mw-1)

Solution (Python):
import sys
input = sys.stdin.readline

H, W, M = map(int, input().split())
st = set()
row = [0] * H
col = [0] * W
for _ in range(M):
    h, w = map(lambda x: int(x) - 1, input().split())
    st.add((h, w))
    row[h] += 1
    col[w] += 1
maxrow = []
maxcol = []
mr = max(row)
for i, r in enumerate(row):
    if r == mr:
        maxrow.append(i)
mc = max(col)
for j, c in enumerate(col):
    if c == mc:
        maxcol.append(j)
if len(maxrow) * len(maxcol) > M:
    print(mr + mc)
else:
    ok = False
    for r in maxrow:
        for c in maxcol:
            if (r, c) not in st:
                print(mr + mc)
                ok = True
                break
        if ok:
            break
    if not ok:
        print(mr + mc - 1)

Solution (Python):
import sys
import math
import copy
from heapq import heappush, heappop, heapify
from functools import cmp_to_key
from bisect import bisect_left, bisect_right
from collections import defaultdict, deque, Counter



input = sys.stdin.readline
getS = lambda: input().strip()
getN = lambda: int(input())
getList = lambda: list(map(int, input().split()))
getZList = lambda: [int(x) - 1 for x in input().split()]

INF = float("inf")
MOD = 10**9 + 7
divide = lambda x: pow(x, MOD-2, MOD)

def nck(n, k, kaijyo):
    return (npk(n, k, kaijyo) * divide(kaijyo[k])) % MOD

def npk(n, k, kaijyo):
    if k == 0 or k == n:
        return n % MOD
    return (kaijyo[n] * divide(kaijyo[n-k])) % MOD

def fact_and_inv(SIZE):
    inv = [0] * SIZE  
    fac = [0] * SIZE  
    finv = [0] * SIZE  
    inv[1] = 1
    fac[0] = fac[1] = 1
    finv[0] = finv[1] = 1
    for i in range(2, SIZE):
        inv[i] = MOD - (MOD // i) * inv[MOD % i] % MOD
        fac[i] = fac[i - 1] * i % MOD
        finv[i] = finv[i - 1] * inv[i] % MOD

    return fac, finv

def renritsu(A, Y):
    
    
    
    A = np.matrix(A)
    Y = np.matrix(Y)
    Y = np.reshape(Y, (-1, 1))
    X = np.linalg.solve(A, Y)

    
    return X.flatten().tolist()[0]

class TwoDimGrid:
    
    def __init__(self, h, w, wall="
        self.h = h
        self.w = w
        self.size = (h+2) * (w+2)
        self.wall = wall
        self.get_grid()
        

    def get_grid(self):
        grid = [self.wall * (self.w + 2)]
        for i in range(self.h):
            grid.append(self.wall + getS() + self.wall)

        grid.append(self.wall * (self.w + 2))
        self.grid = grid
    def init_cost(self):
        self.cost = [INF] * self.size

    def pos(self, x, y):
        
        return y * (self.w + 2) + x
    def getgrid(self, x, y):
        return self.grid[y][x]
    def get(self, x, y):
        return self.cost[self.pos(x, y)]
    def set(self, x, y, v):
        self.cost[self.pos(x, y)] = v
        return
    def show(self):
        for i in range(self.h+2):
            print(self.cost[(self.w + 2) * i:(self.w + 2) * (i+1)])
    def showsome(self, tgt):
        for t in tgt:
            print(t)
        return
    def showsomejoin(self, tgt):
        for t in tgt:
            print("".join(t))
        return

    def search(self):
        grid = self.grid
        move = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        move_eight = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
        
        
        
        
        

def solve():
    h, w, m = getList()
    gg = defaultdict(list)
    hh = defaultdict(list)
    ald = set()
    for i in range(m):
        a, b = getList()
        gg[a].append(b)
        hh[b].append(a)
        ald.add(a * 10 ** 6 + b)
    ma = -1
    ai = []
    for i in range(h+1):
        if ma < len(gg[i]):
            ma = len(gg[i])
            ai = [i]
        elif ma == len(gg[i]):
            ai.append(i)
    mb = -1
    bi = []
    for i in range(w+1):
        if mb < len(hh[i]):
            mb = len(hh[i])
            bi = [i]
        elif mb == len(hh[i]):
            bi.append(i)
    
    
    ans = ma + mb
    for aa in ai:
        for bb in bi:
            if (aa * 10 ** 6 + bb) not in ald:
                print(ans)
                return

    print(ans-1)
    return

def main():
    n = getN()
    for _ in range(n):
        solve()

    return
if __name__ == "__main__":
    
    solve()

Solution (Python):

import math
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
mod = 10 ** 9 + 7
mod1 = 998244353


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)


class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")


sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")



class SegmentTree:
    def __init__(self, data, default=0, func=lambda a, b: a + b):
        """initialize the segment tree with data"""
        self._default = default
        self._func = func
        self._len = len(data)
        self._size = _size = 1 << (self._len - 1).bit_length()

        self.data = [default] * (2 * _size)
        self.data[_size:_size + self._len] = data
        for i in reversed(range(_size)):
            self.data[i] = func(self.data[i + i], self.data[i + i + 1])

    def __delitem__(self, idx):
        self[idx] = self._default

    def __getitem__(self, idx):
        return self.data[idx + self._size]

    def __setitem__(self, idx, value):
        idx += self._size
        self.data[idx] = value
        idx >>= 1
        while idx:
            self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
            idx >>= 1

    def __len__(self):
        return self._len

    def query(self, start, stop):
        if start == stop:
            return self.__getitem__(start)
        stop += 1
        start += self._size
        stop += self._size

        res = self._default
        while start < stop:
            if start & 1:
                res = self._func(res, self.data[start])
                start += 1
            if stop & 1:
                stop -= 1
                res = self._func(res, self.data[stop])
            start >>= 1
            stop >>= 1
        return res

    def __repr__(self):
        return "SegmentTree({0})".format(self.data)



class Factorial:
    def __init__(self, MOD):
        self.MOD = MOD
        self.factorials = [1, 1]
        self.invModulos = [0, 1]
        self.invFactorial_ = [1, 1]

    def calc(self, n):
        if n <= -1:
            print("Invalid argument to calculate n!")
            print("n must be non-negative value. But the argument was " + str(n))
            exit()
        if n < len(self.factorials):
            return self.factorials[n]
        nextArr = [0] * (n + 1 - len(self.factorials))
        initialI = len(self.factorials)
        prev = self.factorials[-1]
        m = self.MOD
        for i in range(initialI, n + 1):
            prev = nextArr[i - initialI] = prev * i % m
        self.factorials += nextArr
        return self.factorials[n]

    def inv(self, n):
        if n <= -1:
            print("Invalid argument to calculate n^(-1)")
            print("n must be non-negative value. But the argument was " + str(n))
            exit()
        p = self.MOD
        pi = n % p
        if pi < len(self.invModulos):
            return self.invModulos[pi]
        nextArr = [0] * (n + 1 - len(self.invModulos))
        initialI = len(self.invModulos)
        for i in range(initialI, min(p, n + 1)):
            next = -self.invModulos[p % i] * (p // i) % p
            self.invModulos.append(next)
        return self.invModulos[pi]

    def invFactorial(self, n):
        if n <= -1:
            print("Invalid argument to calculate (n^(-1))!")
            print("n must be non-negative value. But the argument was " + str(n))
            exit()
        if n < len(self.invFactorial_):
            return self.invFactorial_[n]
        self.inv(n)  
        nextArr = [0] * (n + 1 - len(self.invFactorial_))
        initialI = len(self.invFactorial_)
        prev = self.invFactorial_[-1]
        p = self.MOD
        for i in range(initialI, n + 1):
            prev = nextArr[i - initialI] = (prev * self.invModulos[i % p]) % p
        self.invFactorial_ += nextArr
        return self.invFactorial_[n]


class Combination:
    def __init__(self, MOD):
        self.MOD = MOD
        self.factorial = Factorial(MOD)

    def ncr(self, n, k):
        if k < 0 or n < k:
            return 0
        k = min(k, n - k)
        f = self.factorial
        return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD



def powm(a, n, m):
    if a == 1 or n == 0:
        return 1
    if n % 2 == 0:
        s = powm(a, n // 2, m)
        return s * s % m
    else:
        return a * powm(a, n - 1, m) % m



def sort_list(list1, list2):
    zipped_pairs = zip(list2, list1)

    z = [x for _, x in sorted(zipped_pairs)]

    return z



def product(l):
    por = 1
    for i in range(len(l)):
        por *= l[i]
    return por



def binarySearchCount(arr, n, key):
    left = 0
    right = n - 1

    count = 0

    while (left <= right):
        mid = int((right + left) / 2)

        
        
        if (arr[mid] < key):
            count = mid + 1
            left = mid + 1

        
        else:
            right = mid - 1

    return count



def countdig(n):
    c = 0
    while (n > 0):
        n //= 10
        c += 1
    return c
def binary(x, length):
    y = bin(x)[2:]
    return y if len(y) >= length else "0" * (length - len(y)) + y

def countGreater(arr, n, k):
    l = 0
    r = n - 1

    
    
    leftGreater = n

    
    while (l <= r):
        m = int(l + (r - l) / 2)
        if (arr[m] >= k):
            leftGreater = m
            r = m - 1

        
        
        else:
            l = m + 1

    
    
    return (n - leftGreater)



class BinaryTrie:
    class Node:
        def __init__(self, bit: bool = False):
            self.bit = bit  
            self.children = []
            self.count = 0  
            self.counter = 1  

    def __init__(self, size):
        self.root = BinaryTrie.Node()
        self.size = size  

    def convert(self, key):
        """Converts key from string/integer to a list of boolean values!"""
        bits = []
        if isinstance(key, int):
            key = bin(key)[2:]
        if isinstance(key, str):
            for i in range(self.size - len(key)):
                bits += [False]
            for i in key:
                if i == "0":
                    bits += [False]
                else:
                    bits += [True]
        else:
            return list(key)
        return bits

    def add(self, key):
        """Add a key to the trie!"""
        node = self.root
        bits = self.convert(key)
        for bit in bits:
            found_in_child = False
            for child in node.children:
                if child.bit == bit:
                    child.counter += 1
                    node = child
                    found_in_child = True
                    break
            if not found_in_child:
                new_node = BinaryTrie.Node(bit)
                node.children.append(new_node)
                node = new_node
        node.count += 1

    def remove(self, key):
        """Removes a key from the trie! If there are multiple occurences, it removes only one of them."""
        node = self.root
        bits = self.convert(key)
        nodelist = [node]
        for bit in bits:
            for child in node.children:
                if child.bit == bit:
                    node = child
                    node.counter -= 1
                    nodelist.append(node)
                    break
        node.count -= 1
        if not node.children and not node.count:
            for i in range(len(nodelist) - 2, -1, -1):
                nodelist[i].children.remove(nodelist[i + 1])
                if nodelist[i].children or nodelist[i].count:
                    break

    def query(self, prefix, root=None):
        """Search for a prefix in the trie! Returns the node if found, otherwise 0."""
        if not root: root = self.root
        node = root
        if not root.children:
            return 0
        for bit in prefix:
            bit_not_found = True
            for child in node.children:
                if child.bit == bit:
                    bit_not_found = False
                    node = child
                    break
            if bit_not_found:
                return 0
        return node

class TrieNode:

    
    def __init__(self):
        self.children = [None] * 26
        self.data=0
        self.isEndOfWord = False


class Trie:

    
    def __init__(self):
        self.root = self.getNode()

    def getNode(self):

        
        return TrieNode()

    def _charToIndex(self, ch):

        
        
        

        return ord(ch) - ord('a')

    def insert(self, key,val):
        pCrawl = self.root
        length = len(key)
        for level in range(length):
            index = self._charToIndex(key[level])

            
            if not pCrawl.children[index]:
                pCrawl.children[index] = self.getNode()
            pCrawl = pCrawl.children[index]
            pCrawl.data+=val
        pCrawl.isEndOfWord = True

    def search(self, key):

        
        
        
        pCrawl = self.root
        length = len(key)
        c=0
        for level in range(length):
            index = self._charToIndex(key[level])
            if not pCrawl.children[index]:
                return False
            pCrawl = pCrawl.children[index]
        return pCrawl!=None
    def present(self, key):
        ans=0
        pCrawl = self.root
        length = len(key)
        c=0
        for level in range(length):
            index = self._charToIndex(key[level])
            if not pCrawl.children[index]:
                return False
            pCrawl = pCrawl.children[index]
            ans+=pCrawl.data
        if pCrawl!=None:
            return ans
        return -1

h,w,m=map(int,input().split())
d=defaultdict(int)
d1=defaultdict(int)
tot=set()
for i in range(m):
    a,b=map(int,input().split())
    d[a]+=1
    d1[b]+=1
    tot.add((a,b))
m=max(d.values())
m1=max(d1.values())
s=set()
s1=set()
for i in d:
    if d[i]==m:
        s.add(i)
for i in d1:
    if d1[i]==m1:
        s1.add(i)
c=set()
for i in tot:
    if i[0] in s and i[1] in s1:
        c.add(i)

if len(c)==len(s)*len(s1):
    print(m+m1-1)
else:
    print(m+m1)

Solution (Python):
import sys

sys.setrecursionlimit(500005)
stdin = sys.stdin

ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline().strip()

h, w, m = na()
rs = [0] * h
cs = [0] * w

se = set()
for i in range(m):
    r, c = na()
    rs[r-1] += 1
    cs[c-1] += 1
    se.add((r-1)*w+c-1)

rmax = max(rs)
cmax = max(cs)

remax = rs.count(rmax)
cemax = cs.count(cmax)
if remax * cemax > m:
    print(rmax + cmax)
    sys.exit(0)

rmaxs = [i for i, _ in enumerate(rs) if _ == rmax]
cmaxs = [i for i, _ in enumerate(cs) if _ == cmax]
for r in rmaxs:
    for c in cmaxs:
        if r*w+c not in se:
            print(rmax + cmax)
            sys.exit(0)
print(rmax + cmax - 1)

Solution (Python):
import collections
import sys
import math
sys.setrecursionlimit(10 ** 7)
def input() : return sys.stdin.readline().strip()
def INT()   : return int(input())
def MAP()   : return map(int,input().split())
def LIST()  : return list(MAP())
def NIJIGEN(H): return [list(input()) for i in range(H)]
H,W,M=map(int,input().split())
A=list()
B=list()
for i in range(M):
  a,b=map(int,input().split())
  A.append(a)
  B.append(b)
c = collections.Counter(A)
s=c.most_common()
k=s[0][0]
t=s[0][1]
L=list()
for i in range(M):
  if A[i]!=k:
    L.append(B[i])
c = collections.Counter(L)
s=c.most_common()
if len(s)!=0:
  ans=s[0][1]+t
else:
  ans=t
c = collections.Counter(B)
s=c.most_common()
k=s[0][0]
t=s[0][1]
L=list()
for i in range(M):
  if B[i]!=k:
    L.append(A[i])
c = collections.Counter(L)
s=c.most_common()
if len(s)!=0:
  q=s[0][1]+t
else:
  q=t
ans=max(ans,q)
print(ans)

Solution (Python):
from collections import defaultdict

H, W, m = map(int, input().split())
h_s = [0 for _ in range(H)]
w_s = [0 for _ in range(W)]
dd = defaultdict(bool)
for _ in range(m):
    h, w = map(int, input().split())
    h_s[h - 1] += 1
    w_s[w - 1] += 1
    dd[str(h - 1) + "-" + str(w - 1)] = True

max_h = max(h_s)
max_w = max(w_s)
hh = []
ww = []
for i, h in enumerate(h_s):
    if h == max_h:
        hh.append(i)
for i, w in enumerate(w_s):
    if w == max_w:
        ww.append(i)
ans = max_h + max_w - 1
for h in hh:
    for w in ww:
        if not dd[str(h) + "-" + str(w)]:
            print(ans + 1)
            exit()
print(ans)