#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
#define rep(i,n) for (ll i = 0; i < (n); ++i)
#define vcout(v) rep(i,v.size()) cout << v[i] << " "; cout << endl
#define mcout(m) rep(j,m.size()){vcout(m[j]);}
const ll MOD = 1e9 + 7;

const ll MAXV = 100 * 2;
const ll INF = 1e18;
/*
// 行先、容量、逆辺
struct edge{ll to, cap, rev;};

vector<edge> G[MAXV];
ll level[MAXV]; // sからの距離
ll iter[MAXV]; // どこまで調べ終わったか

void add_edge(ll from, ll to, ll cap){
	G[from].push_back(edge{to,cap,G[to].size()});
	G[to].push_back(edge{from,0,G[from].size()-1});
}

// sからの距離をbfsで計算
void bfs(ll s){
	memset(level, -1, sizeof(level));
	queue<ll> q;
	level[s] = 0;
	q.push(s);

	while(!q.empty()){
		ll v = q.front(); q.pop();
		rep(i,G[v].size()){
			edge &e = G[v][i];
			if(e.cap > 0 && level[e.to] < 0){
				level[e.to] = level[v] + 1;
				q.push(e.to);
			}
		}
	}
}

// 増加パスをdfsで探索
ll dfs(ll v, ll t, ll f){
	if(v == t) return f;

	for(ll &i = iter[v]; i < G[v].size(); i++){
		edge &e = G[v][i];
		if(e.cap > 0 && level[v] < level[e.to]){
			ll d = dfs(e.to, t, min(f,e.cap));
			if(d > 0){
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}

	return 0;
}

// sからtへの最大流を求める
ll max_flow(ll s, ll t){
	ll flow = 0;
	while(true){
		bfs(s);
		if(level[t] < 0) return flow;
		memset(iter, 0, sizeof(iter));
		ll f;
		while( (f = dfs(s,t,INF)) > 0){
			flow += f;
		}
	}
}
*/


// dinic
struct max_flow {
    struct edge { ll to, cap, rev; };
    ll V;
    vector<vector<edge>> G;
    vector<ll> itr, level;

    max_flow(ll V) : V(V) { G.assign(V,vector<edge>()); }

    void add_edge(ll from, ll to, ll cap) {
        G[from].push_back((edge) {to, cap, (ll) G[to].size()});
        G[to].push_back((edge) {from, 0, (ll) G[from].size()-1});
    }

    void bfs(ll s) {
        level.assign(V,-1);
        queue<ll> q;
        level[s] = 0; q.push(s);
        while (!q.empty()) {
            ll v = q.front(); q.pop();
            for(auto &e: G[v]){
                if (e.cap > 0 and level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    q.push(e.to);
                }
            }
        }
    }

    ll dfs(ll v, ll t, ll f) {
        if (v == t) return f;
        for (ll& i = itr[v]; i < (ll) G[v].size(); ++i) {
            edge& e = G[v][i];
            if (e.cap > 0 and level[v] < level[e.to]) {
                ll d = dfs(e.to, t, min(f, e.cap));
                if (d > 0) {
                    e.cap -= d;
                    G[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

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

void mainsolve(){

	ll n;
	cin >> n;

	vector<ll> a(n),b(n),c(n),d(n);

	rep(i,n) cin >> a[i] >> b[i];
	rep(i,n) cin >> c[i] >> d[i];

	// 0 - n-1 red
	// n - 2n-1 blue
	ll s = 2*n;
	ll t = s+1;

	max_flow dinic(2*n+2);

	rep(i,n) dinic.add_edge(s, i, 1);
	rep(i,n) dinic.add_edge(n+i, t, 1);

	rep(i,n){
		rep(j,n){
			if(a[i] < c[j] && b[i] < d[j]) dinic.add_edge(i, n+j, 1);
		}
	}

	cout << dinic.run(s,t) << endl;
	return;
}

int main(){
	
	//ll TC;cin>>TC;rep(I,TC){cout<<"case:"<<I+1<<"---"<<endl; // comment out!
		mainsolve();
	//} // comment out!
	return 0;
}

Measured memory_bytes: 512