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)

// This code is generated by [cargo-atcoder](https://github.com/tanakh/cargo-atcoder)
// Original source code:
/*
use proconio::input;
#[allow(unused_imports)]
use proconio::marker::*;
#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
#[allow(unused_imports)]
use std::f64::consts::*;

#[allow(unused)]
const INF: usize = std::usize::MAX / 4;
#[allow(unused)]
const M: usize = 1000000007;

fn dfs(
    graph: &Vec<Vec<(usize, isize)>>,
    u: usize,
    t: usize,
    f: isize,
    capacity: &mut HashMap<(usize, usize), isize>,
    visited: &mut HashSet<usize>,
) -> isize {
    if u == t {
        return f;
    }
    visited.insert(u);
    for &(v, _) in &graph[u] {
        let c = capacity[&(u, v)];
        if visited.contains(&v) || c <= 0 {
            continue;
        }
        let d = dfs(graph, v, t, min(f, c), capacity, visited);
        if d > 0 {
            *capacity.get_mut(&(u, v)).unwrap() -= d;
            *capacity.get_mut(&(v, u)).unwrap() += d;
            return d;
        }
    }
    0
}

fn ford_fulerson(graph: &Vec<Vec<(usize, isize)>>, s: usize, t: usize) -> isize {
    let n = graph.len();
    let mut capacity = HashMap::new();
    for u in 0..n {
        for &(v, c) in &graph[u] {
            capacity.insert((u, v), c);
        }
    }
    let mut flow = 0;
    loop {
        let mut visited = HashSet::new();
        let f = dfs(graph, s, t, INF as isize, &mut capacity, &mut visited);
        if f == 0 {
            break;
        }
        flow += f;
    }
    flow
}

fn main() {
    input! {
        n: usize,
        ab: [(usize, usize); n],
        cd: [(usize, usize); n],
    }

    let mut graph = vec![vec![]; 2 * n + 2];
    for i in 0..n {
        graph[0].push((i + 1, 1));
        graph[i + 1].push((0, 0));
        graph[n + i + 1].push((2 * n + 1, 1));
        graph[2 * n + 1].push((n + i + 1, 0));
    }
    for i in 0..n {
        let (ai, bi) = ab[i];
        for j in 0..n {
            let (cj, dj) = cd[j];
            if ai < cj && bi < dj {
                graph[i + 1].push((n + j + 1, 1));
                graph[n + j + 1].push((i + 1, 0));
            }
        }
    }
    eprintln!("{:?}", graph);
    println!("{}", ford_fulerson(&graph, 0, 2 * n + 1));
}
*/

fn main() {
    let exe = "/tmp/bin5C1FB2FF";
    std::io::Write::write_all(&mut std::fs::File::create(exe).unwrap(), &decode(BIN)).unwrap();
    std::fs::set_permissions(exe, std::os::unix::fs::PermissionsExt::from_mode(0o755)).unwrap();
    std::process::exit(std::process::Command::new(exe).status().unwrap().code().unwrap())
}

fn decode(v: &str) -> Vec<u8> {
    let mut ret = vec![];
    let mut buf = 0;
    let mut tbl = vec![64; 256];
    for i in 0..64 { tbl[TBL[i] as usize] = i as u8; }
    for (i, c) in v.bytes().filter_map(|c| { let c = tbl[c as usize]; if c < 64 { Some(c) } else { None } }).enumerate() {
        match i % 4 {
            0 => buf = c << 2,
            1 => { ret.push(buf | c >> 4); buf = c << 4; }
            2 => { ret.push(buf | c >> 2); buf = c << 6; }
            3 => ret.push(buf | c),
            _ => unreachable!(),
        }
    }
    ret
}

const TBL: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const BIN: &'static str = "<base64-encoded ELF executable removed>";