bool DBG = false;
// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
//#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using ll = long long;
using ld = long double;
//using i128 = __int128_t;
//using bint = boost::multiprecision::cpp_int;
//using d1024 = boost::multiprecision::number<mp::cpp_dec_float<1024>>;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define IFOR(i,a,b) for(int i=((b)-1);i>=(a);--i)
#define RPT(i,a,b) for(int i=(a);i<((a)+(b));++i)
#define IRPT(i,a,b) for(int i=((a)+(b)-1);i>=(a);--i)
#define ALL(x) x.begin(),x.end()
#define RALL(x) x.rbegin(),x.rend()
#define fs first
#define sd second
#define couts(x) cout << (x) << (" ")
#define coutn(x) cout << (x) << ("\n")
//#define ncouts(x) numout(x),outst[outst_N++] = ' '
//#define ncoutn(x) numout(x),outst[outst_N++] = '\n'
//#define scouts(x) strout(x),outst[outst_N++] = ' '
//#define scoutn(x) strout(x),outst[outst_N++] = '\n'
#define dcouts(x) if(DBG) couts(x)
#define dcoutn(x) if(DBG) coutn(x)
#define endl "\n"
#define psb push_back
#define ppb pop_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define LBIT(x,a) (((x)>>(a))&1LL)
#define IBIT(x,a) (((x)>>(a))&1)
#define BCOUNT(x) (__builtin_popcount(x))
template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T1, typename T2> std::istream &operator>>(std::istream &is, std::pair<T1,T2> &p){is >> p.first >> p.second; return is; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::deque<T> &vec){ os << "deque["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
/*
std::ostream &operator<<(std::ostream &os, const i128 nu){
  i128 co = nu;
  if(co==0){cout << '0';}
  else{
    string ous; if(co<0){cout<<'-'; co*=-1;}
    while(co){
      ous += (co%10)+'0';
      co /= 10;
    }
    reverse(ALL(ous));
    cout<<ous;
  }
  return os;
}
std::istream &operator>>(std::istream &is, i128 &nu){ string cs; cin >> cs; nu=0;int mn=1; for(auto &x:cs) { if(x!='-'){nu*=10;nu+=(x-'0');} else mn *= -1;} nu *= mn;  return is; }

*/


template<class T> using V = vector<T>;
template<class T> using V2 = V<V<T>>;
template<class T> using V3 = V<V2<T>>;
template<class T> using V4 = V<V3<T>>;


constexpr ll LINF = 1LL << 60;
constexpr int IINF = 1 << 28;
constexpr ll mod =  1'000'000'007;
//constexpr ll mod = 998244353;



int INF = 1<<28;
struct edge {
  int to, cap, rev; 
  edge() : to(0), cap(0), rev(0) {}
  edge(int to, int cap, int rev) : to(to), cap(cap), rev(rev) {}
};
std::ostream &operator<<(std::ostream &os, const edge &e){ os << "[" <<  e.to << ","; os << e.cap << "," << e.rev << "]"; return os; }


void add_edge(V2<edge> &g,int from, int to, int cap){
  g[from].push_back((edge){to, cap, (int)g[to].size()});
  g[to].push_back((edge){from, 0, (int)g[from].size() - 1});
}

void bfs(V2<edge> &g, V<int> &level, int s){
  FOR(i,0,(int)level.size()) level[i] = -1;
  queue<int> q;
  level[s] = 0;
  q.push(s);
  while( !q.empty() ){
    int v = q.front(); q.pop();
    FOR(i,0,(int)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);
      }
    }
  }
}

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


int max_flow(V2<edge> &g, V<int> &level, V<int> &iter, int s, int t){
  int flow = 0;
  for(;;){
    bfs(g, level, s);
    if(level[t] < 0) return flow;
    FOR(i,0, (int)iter.size() ) iter[i] = 0;
    int f;;
    while( (f=dfs(g,level,iter,s,t,INF)) > 0 ){
      flow += f;
    }
  }
  return 0;
}

void solve(){
  int n; cin >> n;
  using P = pair<int,int>;
  V<P> reds(n), blues(n); cin >> reds >> blues;
  sort( ALL(reds) ), sort(ALL(blues));
  
  V2<edge> g(2*n+2); V<int> level(2*n+2), iter(2*n+2);
  
  FOR(i,0,n){
    g[2*n].eb(edge(i,1,g[i].size() ));
    g[i].eb(edge(2*n,0,g[2*n].size()-1 ));
  }
  FOR(i,0,n){
    g[n+i].eb(edge(2*n+1,1,g[2*n+1].size() ));
    g[2*n+1].eb(edge(n+i,0,g[n+i].size()-1 ));
  }
  
  FOR(i,0,n){
    FOR(j,0,n){
      if(reds[i].fs<blues[j].fs && reds[i].sd<blues[j].sd) {
        g[i].eb(edge(n+j,1,g[n+j].size() ));
        g[n+j].eb(edge(i,0,g[i].size()-1 ));
      }
      else {
        //g[i].eb(edge(n+j,0,g[n+j].size() ));
        //g[n+j].eb(edge(i,0,g[i].size()-1 ));
      }
    }
  }
  
  
  
  int ans = max_flow(g, level, iter, 2*n, 2*n+1);
  
  
  cout << ans;
}






int main(void){
  //std::cout << std::fixed << std::setprecision(20);
  cin.tie(0);
  //ios::sync_with_stdio(false);
  solve();
  //printf("%s", outst);
  return 0;
}




Measured memory_bytes: 384