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 System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Contest
{
    class Scanner
    {
        private string[] line = new string[0];
        private int index = 0;
        public string Next()
        {
            if (line.Length <= index)
            {
                line = Console.ReadLine().Split(' ');
                index = 0;
            }
            var res = line[index];
            index++;
            return res;
        }
        public int NextInt()
        {
            return int.Parse(Next());
        }
        public long NextLong()
        {
            return long.Parse(Next());
        }
        public string[] Array()
        {
            line = Console.ReadLine().Split(' ');
            index = line.Length;
            return line;
        }
        public int[] IntArray()
        {
            return Array().Select(int.Parse).ToArray();
        }
        public long[] LongArray()
        {
            return Array().Select(long.Parse).ToArray();
        }
    }

    class Set<T>
    {
        private Node Root;
        public int Count { get; private set; } = 0;
        private readonly Comparison<T> Compare;
        public Set() : this(Comparer<T>.Default) { }
        public Set(IComparer<T> comparer) : this(comparer.Compare) { }
        public Set(Comparison<T> comparison)
        {
            Compare = comparison;
        }
        public class Node
        {
            public T Val;
            public Node Parent, High, Low;
            public Node(T val, Node parent)
            {
                Val = val;
                Parent = parent;
            }
        }
        /// <summary>
        /// 要素の追加
        /// </summary>
        /// <param name="item">追加する要素</param>
        /// <returns></returns>
        public void Insert(T item)
        {
            if (Root == null)
            {
                Root = new Node(item, null);
                return;
            }
            Node node = Root;
            Node parent = null;
            bool high = false;
            while (node != null)
            {
                parent = node;
                if (Compare(item, node.Val) > 0)
                {
                    node = node.High;
                    high = true;
                }
                else
                {
                    node = node.Low;
                    high = false;
                }
            }
            node = new Node(item, parent);
            if (high)
            {
                parent.High = node;
            }
            else
            {
                parent.Low = node;
            }
        }
        /// <summary>
        /// 要素の削除
        /// </summary>
        /// <param name="item"></param>
        public void Erase(T item)
        {
            Node node = LowerBound(item);
            if (node == null) return;
            if (Compare(node.Val, item) == 0)
            {
                Erase(node);
            }
        }
        public void Erase(Node node)
        {
            bool hasLow = node.Low != null;
            bool hasHigh = node.High != null;
            Node connect = null;
            if (hasHigh)
            {
                if (hasLow)
                {
                    Node p = node;
                    Node n = node.Low;
                    while (n != null)
                    {
                        p = n;
                        n = n.High;
                    }
                    node.Val = p.Val;
                    Erase(p);
                    return;
                }
                else
                {
                    connect = node.High;
                }
            }
            else
            {
                if (hasLow)
                {
                    connect = node.Low;
                }
                else
                {
                    connect = null;
                }
            }
            var parent = node.Parent;
            if (connect != null)
            {
                connect.Parent = parent;
            }
            if (parent == null)
            {
                Root = connect;
            }
            else
            {
                if (Compare(node.Val, parent.Val) > 0)
                {
                    parent.High = connect;
                }
                else
                {
                    parent.Low = connect;
                }
            }
        }
        /// <summary>
        /// item以上の要素の検索
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Node LowerBound(T item)
        {
            Node node = Root;
            Node parent = null;
            Node result = null;
            while (node != null)
            {
                parent = node;
                if (Compare(node.Val, item) >= 0)
                {
                    if (result == null || Compare(result.Val, node.Val) > 0)
                    {
                        result = node;
                    }
                    node = node.Low;
                }
                else
                {
                    node = node.High;
                }
            }
            return result;
        }
        /// <summary>
        /// itemより大きい要素の検索
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Node UpperBound(T item)
        {
            Node node = Root;
            Node parent = null;
            Node result = null;
            while (node != null)
            {
                parent = node;
                if (Compare(node.Val, item) > 0)
                {
                    if (result == null || Compare(result.Val, node.Val) > 0)
                    {
                        result = node;
                    }
                    node = node.Low;
                }
                else
                {
                    node = node.High;
                }
            }
            return result;
        }
    }

    struct P
    {
        public int X, Y;
        public bool Red;
        public P(int x, int y, bool red)
        {
            X = x;
            Y = y;
            Red = red;
        }
    }

    class Program
    {
        private int N;
        private P[] Arr;
        private void Scan()
        {
            var sc = new Scanner();
            N = sc.NextInt();
            Arr = new P[N * 2];
            for (int i = 0; i < N; i++)
            {
                Arr[i] = new P(sc.NextInt(), sc.NextInt(), true);
            }
            for (int i = 0; i < N; i++)
            {
                Arr[i + N] = new P(sc.NextInt(), sc.NextInt(), false);
            }
        }

        public void Solve()
        {
            Scan();
            var set = new Set<int>((a, b) => -a.CompareTo(b));
            Array.Sort(Arr, (a, b) => a.X.CompareTo(b.X));
            int cnt = 0;
            foreach (P p in Arr)
            {
                if (p.Red)
                {
                    set.Insert(p.Y);
                }
                else
                {
                    var r = set.UpperBound(p.Y);
                    if (r != null)
                    {
                        //Console.WriteLine($"{r.Val} {p.Y}");
                        cnt++;
                        set.Erase(r);
                    }
                }
            }
            Console.WriteLine(cnt);
        }

        static void Main(string[] args)
        {
            new Program().Solve();
        }
    }
}