// Slower C++ solution:
#include <iostream>

#include <string.h>

#include <string>

using namespace std;

const int MAXN = 510;

int uN,vN;//u,v的数目，使用前面必须赋值

int g[MAXN][MAXN];//邻接矩阵

int linker[MAXN];

bool used[MAXN];

int temp;

struct node1{

	int x,y;

}a[105];

struct node2{

	int x,y;

}b[105];

bool dfs(int u)

{

    //if (u!=temp) printf("重新给点%d寻找匹配\n",u);

    for(int v = 0; v < vN; v++)

        if(g[u][v] && !used[v])

        {

            used[v] = true;

            if(linker[v] == -1 || dfs(linker[v]))

            {

                //printf("给点%d匹配到了点%d\n",u,v);

                linker[v] = u;

                return true;

            }

        }

        //printf("失败，没有再找到%d的匹配\n",u);

    return false;

}

int hungary()

{

    int res = 0;

    memset(linker,-1,sizeof(linker));

    for(int u = 0; u < uN; u++)

    {

       // printf("开始给点%d进行匹配\n",u);

        //temp=u;

        memset(used,false,sizeof(used));

        if(dfs(u))res++;

    }

    return res;

}

int main()

{

	int n; 

    while (~scanf("%d",&n))

    {

    	vN=n;

    	uN=n;

        memset(g,0,sizeof(g));

        for (int i=0;i<n;i++)

        {

            scanf("%d%d",&a[i].x,&a[i].y);

        }

        for (int i=0;i<n;i++)

        {

            scanf("%d%d",&b[i].x,&b[i].y);

        }

        for(int i=0;i<n;i++){

        	for(int j=0;j<n;j++){

        		if(a[i].x<b[j].x&&a[i].y<b[j].y)

        		g[i][j]=1;

			}

		}

        printf("%d\n",hungary());

    }

}

// Faster C++ solution for the same problem (measured speedup: 2.0096774547991716x):


#include "bits/stdc++.h"



using namespace std;

using ll = long long;

const double pi = acos(-1);

#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)

#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)

#define REP(i,n) FOR(i,0,n)

#define RREP(i,n) RFOR(i,0,n)

#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME

#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)

#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)

template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) {

	REP(i, v.size()) { if (i)os << " "; os << v[i]; }return os;

}

template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) {

	REP(i, v.size()) { if (i)os << endl; os << v[i]; }return os;

}



const ll INF = 1LL << 60;

ll MOD = 1000000007;

ll _MOD = 1000000009;

double EPS = 1e-10;



#define int long long



const ll dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };



inline void my_io() {



	std::ios::sync_with_stdio(false);



	std::cin.tie(0);



	cout << fixed << setprecision(10);



}



int x, y, e;



vector<vector<int>>G;//グラフの隣接リスト表現



vector<int>match;//マッチングのペア



vector<bool>used;//同一頂点を始点としたDFSを行わないようにする



				 //uとvを結ぶ辺をグラフに追加する



void add_edge(int u, int v) {



	G[u].push_back(v);



	G[v].push_back(u);



}



//増加パスをDFSで探す



bool bi_dfs(int v) {



	used[v] = true;



	for (int i = 0; i<G[v].size(); i++) {



		int u = G[v][i], w = match[u];



		if (w < 0) {



			match[v] = u;



			match[u] = v;



			return true;



		}



		else if (used[w] == false) {



			if (bi_dfs(w)) {



				match[v] = u;



				match[u] = v;



				return true;



			}



		}



	}



	return false;



}



//二部グラフの最大マッチングを求める



int bipartitea_matching() {



	int res = 0;



	fill(match.begin(), match.end(), -1);



	for (int v = 0; v<x + y; v++) {



		if (match[v]<0) {//頂点vのマッチングのペアが現時点でない場合



			fill(used.begin(), used.end(), false);



			if (bi_dfs(v)) {



				res++;



			}



		}



	}



	return res;



}







signed main() {

	ll n;

	vector<pair<ll, ll>> v1, v2;



	cin >> n;



	x = n;

	y = n;



	G.resize(x + y);



	match.resize(x + y);



	used.resize(x + y);



	REP(i, n) {

		ll a, b;

		cin >> a >> b;

		v1.push_back(make_pair(a, b));

	}



	REP(i, n) {

		ll c, d;

		cin >> c >> d;

		v2.push_back(make_pair(c, d));

	}



	REP(i, n) {

		REP(j, n) {

			if (v1[i].first < v2[j].first && v1[i].second < v2[j].second) {

				add_edge(i, j + n);

			}

		}

	}



	cout << bipartitea_matching() << endl;



	return 0;



}