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 Scala (2.13.1) (judge verdict: Accepted)

import java.io.{BufferedOutputStream, BufferedReader, FileOutputStream, InputStreamReader, PrintWriter}
import java.lang

import scala.annotation.tailrec
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag

object Main {
  val DEBUG = false

  lazy val debugOut: PrintWriter = {
    new PrintWriter(new BufferedOutputStream(new FileOutputStream("log.txt", true)))
  }

  def log(message: => String): Unit = {
    if (DEBUG) {
      debugOut.println(message)
    }
  }

  def debug(closure: => Unit): Unit = {
    if (DEBUG) {
      closure
    }
  }

  def get[T: ClassTag](implicit in: BufferedReader, converter: String => T): T = {
    converter(in.readLine)
  }

  def getArray[T: ClassTag](implicit in: BufferedReader, converter: String => T): Array[T] = {
    get[String].split("\\s+").map[T](converter)
  }

  implicit val idConverter: String => String = s => s
  implicit val intConverter: String => Int = s => Integer.parseInt(s)
  implicit val longConverter: String => Long = s => lang.Long.parseLong(s)

  def get[T1, T2](
                   implicit in: BufferedReader,
                   converter1: String => T1,
                   converter2: String => T2
                 ): (T1, T2) = {
    getArray[String] match {
      case Array(v1, v2) => (converter1(v1), converter2(v2))
    }
  }

  def get[T1, T2, T3](
                       implicit in: BufferedReader,
                       converter1: String => T1,
                       converter2: String => T2,
                       converter3: String => T3
                     ): (T1, T2, T3) = {
    getArray[String] match {
      case Array(v1, v2, v3) => (converter1(v1), converter2(v2), converter3(v3))
    }
  }

  def get[T1, T2, T3, T4](
                           implicit in: BufferedReader,
                           converter1: String => T1,
                           converter2: String => T2,
                           converter3: String => T3,
                           converter4: String => T4
                         ): (T1, T2, T3, T4) = {
    getArray[String] match {
      case Array(v1, v2, v3, v4) => (converter1(v1), converter2(v2), converter3(v3), converter4(v4))
    }
  }

  implicit class TimesInt(val n: Int) {
    def times(f: Int => Unit): Unit = {
      for (i <- 0 until n) {
        f(i)
      }
    }
  }

  def primes(n: Long): ArrayBuffer[Long] = {
    val buf = ArrayBuffer.empty[Long]
    val s = Math.sqrt(n).toInt

    var v = n
    for (i <- 2 to s) {
      if (v == 1 || v == 0) {
        return buf
      } else {
        while (v % i == 0) {
          buf.append(i)
          v /= i
        }
      }
    }
    if (v > s) {
      buf.append(v)
    }
    buf
  }

  def divisors(n: Int): ArrayBuffer[Int] = {
    val buf = ArrayBuffer.empty[Int]
    val s = Math.sqrt(n).toInt

    for (i <- 1 to s) {
      if (n % i == 0) {
        buf.append(i)
        if (i != n / i) {
          buf.append(n / i)
        }
      }
    }
    buf
  }

  @tailrec
  def gcd(a: Long, b: Long): Long = {
    val reminder = a % b
    if (reminder == 0) {
      b
    } else {
      gcd(b, reminder)
    }
  }

  @tailrec
  def gcd(a: Int, b: Int): Int = {
    val reminder = a % b
    if (reminder == 0) {
      b
    } else {
      gcd(b, reminder)
    }
  }

  def lcm(a: Long, b: Long): Long = {
    a / gcd(a, b) * b
  }

  def toBitArray(n: Int, width: Int): Array[Boolean] = {
    val buf = ArrayBuffer.fill(width)(false)

    @tailrec
    def inner(n: Int, i: Int): Array[Boolean] = {
      buf(i) = (n & 1) == 0
      if (i == 0) {
        buf.toArray
      } else {
        inner(n / 2, i - 1)
      }
    }

    inner(n, width - 1)
  }

  class ModInt[@specialized(Int) T <: Int](v: Long)(implicit val _m: ValueOf[T]) {
    val m: Long = _m.value
    var value: Long = v % m
    if (value < 0L) {
      value += m
    }

    @inline
    def getValue: Long = value

    override def toString: String = value.toString

    def +(other: ModInt[T]): ModInt[T] = new ModInt[T](value) += other

    def +=(other: ModInt[T]): this.type = {
      value += other.getValue
      if (value >= m) {
        value -= m
      }
      this
    }

    def -(other: ModInt[T]): ModInt[T] = new ModInt(value) -= other

    def -=(other: ModInt[T]): this.type = {
      value -= other.getValue
      if (value < 0) {
        value += m
      }
      this
    }

    def *(other: ModInt[T]): ModInt[T] = new ModInt(value) *= other

    def *=(other: ModInt[T]): this.type = {
      value = value * other.getValue % m
      this
    }

    def /(other: ModInt[T]): ModInt[T] = new ModInt(value) /= other

    def /=(other: ModInt[T]): this.type = {
      var a = other.getValue
      var b = m.toLong
      var u = 1L
      var v = 0L

      while (b > 0L) {
        val t = a / b;
        a -= t * b
        a = a ^ b
        b = a ^ b
        a = a ^ b

        u -= t * v
        u = u ^ v
        v = u ^ v
        u = u ^ v
      }

      value = value * u % m
      if (value < 0) {
        value += m
      }
      this
    }

    def modpow(p: Long): ModInt[T] = {
      @tailrec
      def inner(n: ModInt[T], p: Long, acc: ModInt[T]): ModInt[T] = {
        if (p == 0) {
          acc
        } else if ((p & 1) == 0) {
          inner(n *= n, p >> 1, acc)
        } else {
          inner(n *= n, p >> 1, acc *= n)
        }
      }

      inner(new ModInt[T](value), p, new ModInt[T](1))
    }

    override def equals(other: Any): Boolean = {
      other match {
        case other: ModInt[T] =>
          m == other.m && value == other.value
        case _ => false
      }
    }

    override def hashCode(): Int = {
      (m + value).intValue()
    }
  }

  def main(args: Array[String]): Unit = {
    implicit val in: BufferedReader = new BufferedReader(new InputStreamReader(System.in))
    val out = new PrintWriter(new BufferedOutputStream(System.out))

    log("=== start")

    val n = get[Int]
    val reds = Array.fill(n)(get[Int, Int]).sorted(Ordering.by[(Int, Int), Int](_._2).reverse)
    val blues = Array.fill(n)(get[Int, Int]).sorted

    val redMatched = Array.fill(n)(false)

    @tailrec
    def counting(ri: Int, bi: Int, count: Int): Int = {
      if (ri == reds.length) {
        counting(0, bi + 1, count)
      } else if (bi == blues.length) {
        count
      } else if (redMatched(ri)) {
        counting(ri + 1, bi, count)
      } else {
        val (bx, by) = blues(bi)
        val (rx, ry) = reds(ri)
        if (rx < bx && ry < by) {
          redMatched(ri) = true
          counting(0, bi + 1, count + 1)
        } else {
          counting(ri + 1, bi, count)
        }
      }
    }

    out.println(counting(0, 0, 0))

    out.flush()
    log("=== end")
    debug {
      debugOut.flush()
    }
  }
}