#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  for(int i=0;i<(n);++i)
#define REPr(i,n) for(int i=(n)-1;i>=0; --i)
#define FORq(i, m, n) for(int i = (m);i <= (n);++i)
#define FORqr(i, m , n) for(int i = (n);i >=(m);--i)
#define SCD(n) scanf("%d",&n)
#define SCD2(m,n) scanf("%d%d",&m,&n)
#define SCD3(m,n,k) scanf("%d%d%d",&m,&n,&k)
#define SCLLD(n) scanf("%lld",&n)
#define SCLLD2(m,n) scanf("%lld%lld",&m,&n)
#define SCLLD3(m,n,k) scanf("%lld%lld%lld",&m,&n,&k)
#define PB push_back
#define MP make_pair
#define ARSCD(A,N) REP(i,N){SCD(A[i]);}
#define ARSCD1(A,N) FORq(i,1,N){SCD(A[i]);}
#define VSCD(v,N) REP(i,N){int (x); SCD(x); v.PB(x);}
#define VSCLLD(v,N) REP(i,N){long long (x); SCLLD(x); v.PB(x);}
#define PRINTD(n) printf("%d\n",n)
#define PRINTLLD(n) printf("%lld\n",n)
#define DEBUG printf("%s\n","debug")
#define fst first
#define snd second
#define SIN(x,S) (S.count(x) != 0)
#define M0(x) memset(x,0,sizeof(x))
#define FILL(x,y) memset(x,y,sizeof(x))
#define MM(x) memset(x,-1,sizeof(x))
#define ALL(x) (x).begin(),(x).end()
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long> PLL;
typedef vector<int> VI;
typedef vector < VI > VVI;
typedef vector<long long> VL;
typedef long long ll;
typedef long long integer;
////////////////////////////////////////////////////////////////////
const ll MOD = 1000000007;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
////////////////////////////////////////////////////////////////////
struct edge {
	int to,cap,rev; // rev 逆向きに貼る辺(cap=0で初期化)
};
const int V_MAX = 302;
const int INF = 1000000000;
int V,E;

vector<vector<edge>> G(V_MAX);
vector<int>itr, level;

void bfs(int s){
	level.assign(V,-1); //-1 reset
	queue<int> Q;
	level[s] = 0;
	Q.push(s);
	while(!Q.empty()){
		int v = Q.front(); Q.pop();
		REP(i,G[v].size()){
			edge e = G[v][i];
			if ((e.cap > 0) and (level[e.to] < 0)){// cap > 0 && not visited
				level[e.to] = level[v] + 1;
				Q.push(e.to);
			}
		}
	}
}

int dfs(int v,int t,int flow){
	if (v == t) return flow;
	for(int &i = itr[v]; i < (int)G[v].size(); ++i){
		edge& e = G[v][i];
		if ((e.cap > 0) and (level[v] < level[e.to])){
			int d = dfs(e.to,t,min(flow,e.cap));
			if (d>0){
				e.cap -= d;
				G[e.to][e.rev].cap += d; //逆向きに流せる量を増やす
				return d;
			}
			
		}
	}
	return 0;
}

void addedge(int u,int v,int c){
	edge e;
	e.to = v; e.cap = c; e.rev = (int)G[v].size();
	G[u].PB(e);
	e.to = u; e.cap = 0; e.rev = G[u].size()-1;
	G[v].PB(e);
}

bool comp(PII X,PII Y){
    // < true
    if ((X.first < Y.first) and (X.second < Y.second)) return true;
    return false;
}

int main(){
	int N;
    SCD(N);

    V = 2*N+2;
    vector<PII> X;
    REP(i,N){
        int x,y;
        cin >> x >> y;
        X.PB(MP(x,y));
    }

    REP(i,N){
        int x,y;
        cin >> x >> y;
        X.PB(MP(x,y));
    }

    FORq(i,1,N){
        FORq(j,N+1,2*N){
            if (comp(X[i-1],X[j-1])){
                addedge(i,j,1);
            }
        }
    }

    FORq(i,1,N){
        addedge(0,i,1);
    }

    FORq(j,N+1,2*N){
        addedge(j,2*N+1,1);
    }

	int flow = 0; //ans
	int f = 0; //temporary flow

	int s = 0; //start pos
	int t = 2*N+1; // end pos

	while(bfs(s),level[t] >= 0){
		itr.assign(V,0);
		while((f = dfs(s,t,INF)) > 0) flow += f;
	}
	
	PRINTD(flow);
	return 0;
}

Measured memory_bytes: 384