# ２部マッチング

# 最大流

# Ford-Fulkerson

N = int(eval(input()))

A = [list(map(int, input().split())) for _ in range(N)]

B = [list(map(int, input().split())) for _ in range(N)]



# -1: source, 2N: sink

edge = {-1: {}, 2 * N: {}}

for i, a in enumerate(A):

    edge[i] = {}

    edge[-1][i] = 1

    for j, b in enumerate(B):

        j += N

        if j not in edge:

            edge[j] = {}

        edge[j][2 * N] = 1

        if a[0] < b[0] and a[1] < b[1]:

            edge[i][j] = 1



visited = [False] * (2 * N + 2)

def find_route(start, goal, bottleneck):

    global visited

    visited[start] = True

    if start == goal:

        return bottleneck

    for to in edge[start]:

        if visited[to] or edge[start][to] <= 0:

            continue

        flow = find_route(to, goal, min(bottleneck, edge[start][to]))

        if flow > 0:

            edge[start][to] = edge[start].get(to, 0) - flow

            edge[to][start] = edge[to].get(start, 0) + flow

            return flow

    return 0



ans = 0

while True:

    visited = [False] * (2 * N + 2)

    flow = find_route(-1, 2 * N, float('inf'))

    if flow == 0:

        break

    ans += flow

print(ans)
# ２部マッチング

N = int(eval(input()))

A = [list(map(int, input().split())) for _ in range(N)]

B = [list(map(int, input().split())) for _ in range(N)]



def dfs(v, visited):

    for u in edge[v]:

        if u in visited:

            continue

        visited.add(u)

        if matched[u] == -1 or dfs(matched[u], visited):

            matched[u] = v

            return True

    return False



matched = [-1] * N

edge = [set() for _ in range(N)]

for i, a in enumerate(A):

    for j, b in enumerate(B):

        if a[0] < b[0] and a[1] < b[1]:

            edge[i].add(j)

print((sum(dfs(v, set()) for v in range(N))))
# ２部マッチング
# 最大流
# Ford-Fulkerson
N = int(eval(input()))
A = [list(map(int, input().split())) for _ in range(N)]
B = [list(map(int, input().split())) for _ in range(N)]
# -1: source, 2N: sink
edge = {-1: {}, 2 * N: {}}
for i, a in enumerate(A):
    edge[i] = {}
    edge[-1][i] = 1
    for j, b in enumerate(B):
        j += N
        if j not in edge:
            edge[j] = {}
        edge[j][2 * N] = 1
        if a[0] < b[0] and a[1] < b[1]:
            edge[i][j] = 1
visited = [False] * (2 * N + 2)


def find_route(start, goal, bottleneck):
    global visited
    visited[start] = True
    if start == goal:
        return bottleneck
    for to in edge[start]:
        if visited[to] or edge[start][to] <= 0:
            continue
        flow = find_route(to, goal, min(bottleneck, edge[start][to]))
        if flow > 0:
            edge[start][to] = edge[start].get(to, 0) - flow
            edge[to][start] = edge[to].get(start, 0) + flow
            return flow
    return 0


ans = 0
while True:
    visited = [False] * (2 * N + 2)
    flow = find_route(-1, 2 * N, float("inf"))
    if flow == 0:
        break
    ans += flow
print(ans)

# ２部マッチング
N = int(eval(input()))
A = [list(map(int, input().split())) for _ in range(N)]
B = [list(map(int, input().split())) for _ in range(N)]


def dfs(v, visited):
    for u in edge[v]:
        if u in visited:
            continue
        visited.add(u)
        if matched[u] == -1 or dfs(matched[u], visited):
            matched[u] = v
            return True
    return False


matched = [-1] * N
edge = [set() for _ in range(N)]
for i, a in enumerate(A):
    for j, b in enumerate(B):
        if a[0] < b[0] and a[1] < b[1]:
            edge[i].add(j)
print((sum(dfs(v, set()) for v in range(N))))

-# 最大流 -# Ford-Fulkerson -# -1: source, 2N: sink -edge = {-1: {}, 2 * N: {}} -for i, a in enumerate(A): -    edge[i] = {} -    edge[-1][i] = 1 -    for j, b in enumerate(B): -        j += N -        if j not in edge: -            edge[j] = {} -        edge[j][2 * N] = 1 -        if a[0] < b[0] and a[1] < b[1]: -            edge[i][j] = 1 -visited = [False] * (2 * N + 2) -def find_route(start, goal, bottleneck): -    global visited -    visited[start] = True -    if start == goal: -        return bottleneck -    for to in edge[start]: -        if visited[to] or edge[start][to] <= 0: +def dfs(v, visited): +    for u in edge[v]: +        if u in visited: -        flow = find_route(to, goal, min(bottleneck, edge[start][to])) -        if flow > 0: -            edge[start][to] = edge[start].get(to, 0) - flow -            edge[to][start] = edge[to].get(start, 0) + flow -            return flow -    return 0 +        visited.add(u) +        if matched[u] == -1 or dfs(matched[u], visited): +            matched[u] = v +            return True +    return False -ans = 0 -while True: -    visited = [False] * (2 * N + 2) -    flow = find_route(-1, 2 * N, float("inf")) -    if flow == 0: -        break -    ans += flow -print(ans) +matched = [-1] * N +edge = [set() for _ in range(N)] +for i, a in enumerate(A): +    for j, b in enumerate(B): +        if a[0] < b[0] and a[1] < b[1]: +            edge[i].add(j) +print((sum(dfs(v, set()) for v in range(N))))