Problem:
Score : 400 points

Problem Statement

On a two-dimensional plane, there are N red points and N blue points.
The coordinates of the i-th red point are (a_i, b_i), and the coordinates of the i-th blue point are (c_i, d_i).

A red point and a blue point can form a friendly pair when, the x-coordinate of the red point is smaller than that of the blue point, and the y-coordinate of the red point is also smaller than that of the blue point.

At most how many friendly pairs can you form? Note that a point cannot belong to multiple pairs.

Constraints

All input values are integers.

1 \leq N \leq 100

0 \leq a_i, b_i, c_i, d_i < 2N

a_1, a_2, ..., a_N, c_1, c_2, ..., c_N are all different.

b_1, b_2, ..., b_N, d_1, d_2, ..., d_N are all different.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
a_2 b_2
:
a_N b_N
c_1 d_1
c_2 d_2
:
c_N d_N

Output

Print the maximum number of friendly pairs.

Sample Input 1

3
2 0
3 1
1 3
4 2
0 4
5 5

Sample Output 1

2

For example, you can pair (2, 0) and (4, 2), then (3, 1) and (5, 5).

Sample Input 2

3
0 0
1 1
5 2
2 3
3 4
4 5

Sample Output 2

2

For example, you can pair (0, 0) and (2, 3), then (1, 1) and (3, 4).

Sample Input 3

2
2 2
3 3
0 0
1 1

Sample Output 3

0

It is possible that no pair can be formed.

Sample Input 4

5
0 0
7 3
2 2
4 8
1 6
8 5
6 9
5 4
9 1
3 7

Sample Output 4

5

Sample Input 5

5
0 0
1 1
5 5
6 6
7 7
2 2
3 3
4 4
8 8
9 9

Sample Output 5

4

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
using System.Runtime.CompilerServices;
using static MyUtil;

class MyUtil
{
    public static int[] ReadIntArray()
    {
	return ReadLine().Split().Select(x => int.Parse(x)).ToArray();
    }
}



class Program
{
    static int MAX_V = 100 * 100;
    
    class Edge {
	public int to, cap, rev;
	public Edge(int _to, int _cap, int _rev)
	{
	    to = _to; cap = _cap; rev = _rev;
	}
    }

    static List<Edge>[] G;
    static bool[] used;

    static void AddEdge(int from, int to, int cap)
    {
	G[from].Add(new Edge(to, cap, G[to].Count));
	G[to].Add(new Edge(from, 0, G[from].Count - 1));
    }

    static int dfs (int v, int t, int f)
    {
	if (v == t) return f;
	used[v] = true;
	for (int i = 0; i < G[v].Count; i++)
	{
	    Edge e = G[v][i];
	    if (!used[e.to] && e.cap > 0)
	    {
		int d = dfs(e.to, t, Math.Min(f, e.cap));
		if (d > 0)
		{
		    e.cap -= d;
		    G[e.to][e.rev].cap += d;
		    return d;
		}
	    }
	}
	return 0;
    }

    static int MaxFlow(int s, int t)
    {
	int flow = 0;
	while (true)
	{
	    used = new bool[MAX_V];
	    int f = dfs(s, t, 1000000000);
	    if (f == 0) return flow;
	    flow += f;
	}
    }
    
    public static void Main()
    {
	G = new List<Edge>[MAX_V];
	for (int i = 0; i < MAX_V; i++)
	    G[i] = new List<Edge>();

	int n = int.Parse(ReadLine());
	int[] a = new int[n];
	int[] b = new int[n];
	int[] c = new int[n];
	int[] d = new int[n];

	for (int i = 0; i < n; i++)
	{
	    var tmp = ReadIntArray();
	    a[i] = tmp[0]; b[i] = tmp[1];
	}
	for (int i = 0; i < n; i++)
	{
	    var tmp = ReadIntArray();
	    c[i] = tmp[0]; d[i] = tmp[1];
	}

	// node#
	//  red : 1 .. n
	//  blue: n+1 .. 2n
	//  s:0, t: 2n+1
	for (int i = 0; i < n; i++)
	{
	    for (int j = 0; j < n; j++)
	    {
		if (a[i] < c[j] && b[i] < d[j])
		{
		    AddEdge(i+1, n+j+1, 1);
		}
	    }
	}

	for (int i = 1; i <= n; i++)
	{
	    AddEdge(0, i, 1);
	    AddEdge(n+i, 2*n+1, 1);
	}

	WriteLine(MaxFlow(0, 2*n+1));
    }
}