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 Rust (1.15.1) (judge verdict: Accepted)

#[derive(Clone, Copy)]
pub struct Edge {
	pub to: usize,
	pub capacity: i64,
	pub reverse: usize,
}

pub struct Dinic {
	edges: Vec<Vec<Edge>>,
	level: Vec<i64>,
	iter: Vec<usize>,
}

impl Dinic {
	pub fn new(v: usize) -> Self {
		Dinic { edges: vec![vec![]; v], level: vec![0; v], iter: vec![0; v] }
	}

	pub fn add_edge(&mut self, from: usize, to: usize, capacity: i64) {
		let reverse = self.edges[to].len();
		self.edges[from].push(Edge { to: to, capacity: capacity, reverse: reverse });
		let reverse = self.edges[from].len() - 1;
		self.edges[to].push(Edge { to: from, capacity: 0, reverse: reverse });
	}

	fn bfs(&mut self, from: usize) {
		for i in self.level.iter_mut() {
			*i = -1;
		}
		let mut q = std::collections::VecDeque::new();
		self.level[from] = 0;
		q.push_back(from);
		while let Some(v) = q.pop_front() {
			for e in self.edges[v].iter() {
				if e.capacity > 0 && self.level[e.to] < 0 {
					self.level[e.to] = self.level[v] + 1;
					q.push_back(e.to);
				}
			}
		}
	}

	fn dfs(&mut self, v: usize, to: usize, f: i64) -> i64 {
		if v == to {
			return f;
		}
		while self.iter[v] < self.edges[v].len() {
			let i = self.iter[v];
			let e = self.edges[v][i];
			if e.capacity > 0 && self.level[v] < self.level[e.to] {
				let d = self.dfs(e.to, to, std::cmp::min(f, e.capacity));
				if d > 0 {
					self.edges[v][i].capacity -= d;
					self.edges[e.to][e.reverse].capacity += d;
					return d;
				}
			}
			self.iter[v] += 1;
		}
		0
	}

	fn max_flow(&mut self, from: usize, to: usize) -> i64 {
		let mut flow = 0;
		loop {
			self.bfs(from);
			if self.level[to] < 0 {
				break;
			}
			for i in self.iter.iter_mut() {
				*i = 0;
			}
			loop {
				let f = self.dfs(from, to, std::i64::MAX);
				if f > 0 {
					flow += f;
				} else {
					break;
				}
			}
		}
		flow
	}
}

fn main() {
	let mut s = String::new();
	use std::io::Read;
	std::io::stdin().read_to_string(&mut s).unwrap();
	let mut s = s.split_whitespace();
	let n: usize = s.next().unwrap().parse().unwrap();
	let mut dinic = Dinic::new(2 * n + 2);
	let red = (0..n).map(|_| (s.next().unwrap().parse::<u8>().unwrap(), s.next().unwrap().parse::<u8>().unwrap())).collect::<Vec<_>>();
	let blue = (0..n).map(|_| (s.next().unwrap().parse::<u8>().unwrap(), s.next().unwrap().parse::<u8>().unwrap())).collect::<Vec<_>>();
	let from = 2 * n;
	let to = 2 * n + 1;
	for i in 0..n {
		dinic.add_edge(from, i, 1);
		dinic.add_edge(n + i, to, 1);
		for j in 0..n {
			if red[i].0 < blue[j].0 && red[i].1 < blue[j].1 {
				dinic.add_edge(i, n + j, 1);
			}
		}
	}
	let ans = dinic.max_flow(from, to);
	println!("{}", ans);
}