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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define MAXN 500
#define INF 0x3fffffff

int n,m;
int itor[MAXN+5],level[MAXN+5];
pair<int,int> a[MAXN],b[MAXN];
struct node
{
    int v,d,res;
    node(){}
    node(int a,int b,int c)
    {
        v=a,d=b,res=c;
    }
};
vector <node> E[MAXN+5];

void bfs(int s)
{
    memset(level,-1,sizeof level);
    level[s]=0;
    queue <int> q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[u][i].v;
            int d=E[u][i].d;
            if(d>0&&level[v]<0)
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
}

int dfs(int u,int e,int f)
{
    if(u==e)
        return f;
    for(int &i=itor[u];i<E[u].size();i++)
    {
        node now=E[u][i];
        if(now.d>0&&level[u]<level[now.v])
        {
            int ex=dfs(now.v,e,min(f,now.d));
            if(ex>0)
            {
                E[u][i].d-=ex;
                E[now.v][now.res].d+=ex;
                return ex;
            }
        }
    }
    return 0;
}

int Dinic(int s,int t)
{
    int ans=0;
    while(1)
    {
        bfs(s);
        if(level[t]<0)
            break;
        memset(itor,0,sizeof itor);
        int f;
        while((f=dfs(s,t,INF))>0)
            ans+=f;
    }
    return ans;
}

void add_edge(int u,int v,int va)
{
    E[u].push_back(node(v,va,E[v].size()));
    E[v].push_back(node(u,0,E[u].size()-1));
}

int main()
{
    scanf("%d",&n);
    m=2*n+2;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].first,&a[i].second);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&b[i].first,&b[i].second);
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(a[i].first<b[j].first&&a[i].second<b[j].second)
                add_edge(i,j+n,1);
    for(int i=1;i<=n;i++)
        add_edge(2*n+1,i,1),add_edge(i+n,2*n+2,1);
    printf("%d\n",Dinic(2*n+1,2*n+2));
}