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)

#![allow(unused_imports)]
use std::io::{ self, Write };
use std::str::FromStr;
use std::cmp::{ min, max };
use std::collections::{ BinaryHeap, VecDeque };

#[allow(unused_macros)]
macro_rules! trace {
    ($var:expr) => {
        let _ = writeln!(&mut std::io::stderr(), ">>> {} = {:?}", stringify!($var), $var);
    };
    ($($args:expr),*) => { trace!(($($args),*)) }
}

#[allow(unused_macros)]
macro_rules! put {
    ($var:expr) => {
        let _ = writeln!(&mut std::io::stdout(), "{}", $var);
    };
    ($var:expr, $($args:expr),*) => {
        let _ = write!(&mut std::io::stdout(), "{} ", $var);
        put!($($args),*);
    };
}

mod Dinic {
    use std::collections::VecDeque;
    use std::cmp::min;

    pub type Weight = i32;
    pub type WeightedGraph = Vec<Vec<(usize, Weight)>>; // [u][] = (v, w)
    pub type Edge = (usize, usize, Weight);

    pub fn new(n: usize, es: &Vec<Edge>) -> WeightedGraph {
        let mut g: WeightedGraph = vec![vec![]; n];
        for &(u, v, w) in es.iter() {
            g[u].push((v, w));
            g[v].push((u, 0));
        }
        g
    }

    fn levelize(g: &WeightedGraph, s: usize, t: usize, cap: &Vec<Vec<Weight>>, flw: &Vec<Vec<Weight>>) -> Vec<i32> {
        let n = g.len();
        let mut level = vec![-1; n]; level[s] = 0;
        let mut q = VecDeque::new(); q.push_back(s);
        while let Some(u) = q.pop_front() {
            if u == t { break }
            for &(v, _) in g[u].iter() {
                if level[v] == -1 && cap[u][v] != flw[u][v] {
                    level[v] = level[u] + 1;
                    q.push_back(v);
                }
            }
        }
        level
    }

    fn augment(limit: Weight,
               level: &Vec<i32>, mut used: &mut Vec<bool>,
               g: &WeightedGraph, u: usize, t: usize,
               cap: &Vec<Vec<Weight>>, mut flw: &mut Vec<Vec<Weight>>) -> Weight {
        if u == t {
            limit
        } else if used[u] || limit == 0 {
            0
        } else {
            used[u] = true;
            for &(v, _) in g[u].iter() {
                if level[v] > level[u] {
                    let limit2 = min(limit, cap[u][v] - flw[u][v]);
                    let f = augment(limit2, &level, &mut used, &g, v, t, &cap, &mut flw);
                    if f > 0 {
                        flw[u][v] += f; flw[v][u] -= f;
                        used[u] = false;
                        return f;
                    }
                }
            }
            0
        }
    }

    pub fn flow(g: &WeightedGraph, s: usize, t: usize) -> Weight {

        let n = g.len();

        let mut cap = vec![vec![0; n]; n];
        let mut flw = vec![vec![0; n]; n];
        for u in 0..n { for &(v, w) in g[u].iter() { cap[u][v] = w; } }

        let inf = Weight::max_value() / 8;
        let mut sum = 0;
        loop {
            let level = levelize(&g, s, t, &cap, &flw);
            if level[t] == -1 { break }
            let mut used = vec![false; n];
            sum += augment(inf, &level, &mut used, &g, s, t, &cap, &mut flw);
        }

        sum
    }
}

fn main() {
    let mut sc = Scanner::new();
    let n = sc.cin();

    let mut ws = vec![];
    for i in 0..n {
        let a :usize = sc.cin();
        let b :usize = sc.cin();
        ws.push((a, b));
    }

    let mut bs = vec![];
    for i in 0..n {
        let a :usize = sc.cin();
        let b :usize = sc.cin();
        bs.push((a, b));
    }

    let mut es = vec![];

    for i in 0..n {
        for j in 0..n {
            if ws[i].0 < bs[j].0 && ws[i].1 < bs[j].1 {
                es.push((1+i, 1+n+j, 1));
            }
        }
    }
    for i in 0..n {
        es.push((0, 1+i, 1));
        es.push((1+n+i, 2*n+1, 1));
    }

    let g = Dinic::new(2*n+2, &es);
    println!("{}", Dinic::flow(&g, 0, 2*n+1));

}

#[allow(dead_code)]
struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn reserve(&mut self) {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        self.reserve();
        match self.buffer.pop_front().unwrap().parse::<T>() {
            Ok(a) => a,
            Err(_) => panic!("parse err")
        }
    }
}