#include<algorithm>
#include<bitset>
#include<cmath>
#include<complex>
#include<deque>
#include<functional>
#include<iomanip>
#include<iostream>
#include<iterator>
#include<map>
#include<numeric>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>
#include<chrono>
using namespace std;
#define rep(i,n) for(int i=0; i<(n); i++)
#define FOR(i,x,n) for(int i=x; i<(n); i++)
#define vint(a,n) vint a(n); rep(i, n) cin >> a[i];
#define vll(a,n) vll a(n); rep(i, n) cin >> a[i];
#define ALL(n) begin(n),end(n)
#define RALL(n) rbegin(n),rend(n)
#define MOD (1000000007)
// #define MOD (998244353)
#define INF (2e9)
#define INFL (2e18)

typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
using vint=vector<int>;
using vll=vector<ll>;
using vbool=vector<bool>;
template<class T>using arr=vector<vector<T>>;
template<class T>int popcount(T &a){int c=0; rep(i, 8*(int)sizeof(a)){if((a>>i)&1) c++;} return c;}
template<class T>void pr(T x){cout << x << endl;}
template<class T>void prvec(vector<T>& a){rep(i, a.size()-1){cout << a[i] << " ";} pr(a[a.size()-1]);}
template<class T>void prarr(arr<T>& a){rep(i, a.size()) if(a[i].empty()) pr(""); else prvec(a[i]);}
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

struct edge{
    int cap, to;
};
class MaxFlow{
// https://www.hongo.wide.ad.jp/~jo2lxq/dm/lecture/09.pdf
// https://www.slideshare.net/hcpc_hokudai/max-flow
public:
    int n;
    arr<edge> G;
    // TODO: 容量をn x n行列に行列に持たせる。(メモリは犠牲になる)
    // arr<int> flowmat;
    vector<int> path;
    int max_flow_in_path; //そのパスにおける最大値
    int max_flow;

    //無向グラフgを引数に取るコンストラクタ
    MaxFlow(arr<edge> g){
        n = g.size();
        G = g;
        max_flow_in_path = 0;
        max_flow = 0;
    }

    //////////////////// Ford-Fulkerson法による解放 //////////////////////////
    // s ~ tのpathを求めるdfs
    void dfs(int& s, int& t, vector<int> tmp_path, vector<bool>& seen, int m_flow){
        if(max_flow_in_path>0) return;
        tmp_path.push_back(s);
        if(s==t){
            max_flow_in_path = m_flow;
            path = tmp_path;
            return;
        }
        seen[s] = true;
        for(edge& e: G[s]){
            if(seen[e.to]) continue;
            if(e.cap==0) continue;
            dfs(e.to, t, tmp_path, seen, min(m_flow, e.cap));
        }
    }

    // s, tの道を探索し、あればpath, max_flow_in_pathを更新してtrueを返す
    bool findPath(int s, int t){
        vector<int> tmp_path;
        vector<bool> seen(n, false);
        // seen[s] = true;
        max_flow_in_path = 0;

        dfs(s, t, tmp_path, seen, INF);

        if(max_flow_in_path > 0) return true;
        return false;
    }

    // path, max_flow_in_pathを使ってmax_flow, Gをアップデートする。
    void update(){
        // pr(max_flow_in_path);
        // prvec(path);
        rep(i, path.size()-1){
            for(edge& e: G[path[i]]){
                if(e.to != path[i+1]) continue;
                e.cap -= max_flow_in_path;
                break;
            }
            for(edge& e: G[path[i+1]]){
                if(e.to != path[i]) continue;
                e.cap += max_flow_in_path;
                break;
            }
        }
        max_flow += max_flow_in_path;
        return;
    }

    void calcFordFulkerson(int s, int t){
        while(findPath(s, t)) update();
    }

    ///////////// TODO: Dinic法 ///////////////////////////
};

int main()
{
    int n, m; cin >> n;
    vint a(n), b(n), c(n), d(n);
    arr<edge> g(2*n+2);
    rep(i, n){
        cin >> a[i] >> b[i];
    }
    rep(i, n) cin >> c[i] >> d[i];

    rep(i, n){
        g[0].push_back({1, i+1});
        g[i+1].push_back({0, 0});
        g[n+1+i].push_back({1, 2*n+1});
        g[2*n+1].push_back({0, n+1+i});
    }
    rep(i, n) rep(j, n){
        if(a[i] < c[j] && b[i] < d[j]){
            g[i+1].push_back({1, n+1+j});
            g[n+1+j].push_back({0, i+1});
        }
    }
    MaxFlow mf(g);
    mf.calcFordFulkerson(0, 2*n+1);
    pr(mf.max_flow);
    return 0;}

Measured memory_bytes: 3700