#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
using namespace std;
using ll = long long;
using P = pair<int,int>;
template <class T> void chmin(T &a, const T &b) noexcept { if (b < a) a = b; }
template <class T> void chmax(T &a, const T &b) noexcept { if (a < b) a = b; }
void debug_out() { cout << "\n"; }
template <class T, class... Args>
void debug_out(const T &x, const Args &... args) { cout << x << " "; debug_out(args...);}
#ifdef _DEBUG
  #define debug(...) debug_out(__VA_ARGS__)
#else
  #define debug(...) 
#endif

template<typename T>
struct Dinic {
  private:
    const T INF;
    struct edge {
      int to, rev, idx; 
      T cap; 
      bool isrev; 
      edge(){}
      edge(int to,T cap,int rev,bool isrev,int idx=-1):
      to(to),rev(rev),idx(idx),cap(cap),isrev(isrev) {}
    };
    vector<vector<edge> > G;
    vector<int> min_cost, iter;
    
    bool bfs(int s, int t) {
      min_cost.assign(G.size(),-1);
      queue<int> que;
      min_cost[s] = 0;
      que.push(s);
      while(!que.empty() && min_cost[t] == -1) {
        int p = que.front();
        que.pop();
        for(auto &e : G[p]) {
          if(e.cap > 0 && min_cost[e.to] == -1) {
            min_cost[e.to] = min_cost[p] + 1;
            que.push(e.to);
          }
        }
      }
      return min_cost[t] != -1;
    }
    T dfs(int v, const int t, T flow) {
      if(v == t) return flow;
      for(int &i = iter[v]; i < (int)G[v].size(); i++) {
        edge &e = G[v][i];
        if(e.cap > 0 && min_cost[v] < min_cost[e.to]) {
          T d = dfs(e.to, t, min(flow, e.cap));
          if(d == 0) continue;
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
      return 0;
    }
  public:
    Dinic(int n):INF(numeric_limits<T>::max()),G(n) {}
    void add_edge(int from, int to, T cap, int idx=-1) {
      G[from].emplace_back(edge(to, cap, (int)G[to].size(), false, idx));
      G[to].emplace_back(edge(from, 0, (int)G[from].size()-1, true, idx));
    }
    T max_flow(int s, int t) {
      assert(s < (int)G.size());
      assert(t < (int)G.size());
      T flow = 0;
      while(bfs(s,t)) {
        iter.assign(G.size(), 0);
        T f = 0;
        while((f = dfs(s,t,INF)) > 0) flow += f;
      }
      return flow;
    }
    void output() {
      for(int i = 0; i < (int)G.size(); i++) {
        for(auto &e : G[i]) {
          if(e.isrev) continue;
          auto &rev_e = G[e.to][e.rev];
          cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/" << e.cap + rev_e.cap << ")" << endl;
        }
      }
    }
};


int main() {
  std::cin.tie(nullptr);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  int n;
  cin >> n;
  vector<P> a(n),b(n);
  rep(i,n) cin >> a[i].first >> a[i].second;
  rep(i,n) cin >> b[i].first >> b[i].second;

  Dinic<int> dinic(2*n+2);
  rep(i,n) dinic.add_edge(0, i+1,1);
  rep(i,n) dinic.add_edge(n+i+1, 2*n+1,1);
  rep(i,n) {
    rep(j,n) {
      if (a[i].first < b[j].first && a[i].second < b[j].second) {
        dinic.add_edge(i+1, n+j+1, 1);
      }
    }
  }
  int ans = dinic.max_flow(0, 2*n+1);
  cout << ans << endl;
  return 0;
}

Measured memory_bytes: 512