#include<bits/stdc++.h>
using namespace std;

#define ld long double
#define ll long long
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define MP make_pair
const ll MOD = 1e9+7;
//const ll MOD = 998244353;
ll INF = 1e18;
void chmin(ll &a,ll b){if(a>b)a=b;}
void chmax(ll &a,ll b){if(a<b)a=b;}
void pmod(ll &a,ll b){a=(a+b)%MOD;}
void qmod(ll &a,ll b){a=(a*b)%MOD;}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
void ans(bool x,ll y,ll z){if(x)cout<<y<<endl;else cout<<z<<endl;}
void ans(bool x,string y,string z){if(x)cout<<y<<endl;else cout<<z<<endl;}   
ll gcd(ll x,ll y){ll r;while((r=x%y)!=0){x=y;y=r;}return y;}

//BEGIN CUT HERE
template<typename T,bool directed>
struct Dinic{
  struct edge {
    ll to;
    T cap;
    ll rev;
    edge(){}
    edge(ll to,T cap,ll rev):to(to),cap(cap),rev(rev){}
  };

  vector<vector<edge> > G;
  vector<ll> level,iter;

  Dinic(){}
  Dinic(ll n):G(n),level(n),iter(n){}

  ll add_edge(ll from,ll to,T cap){
    G[from].emplace_back(to,cap,G[to].size());
    G[to].emplace_back(from,directed?0:cap,G[from].size()-1);
    return G[to].back().rev;
  }

  void bfs(ll s){
    fill(level.begin(),level.end(),-1);
    queue<ll> que;
    level[s]=0;
    que.emplace(s);
    while(!que.empty()){
      ll v=que.front();que.pop();
      for(ll i=0;i<(ll)G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.emplace(e.to);
        }
      }
    }
  }

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

  T flow(ll s,ll t,T lim){
    T fl=0;
    while(1){
      bfs(s);
      if(level[t]<0||lim==0) break;
      fill(iter.begin(),iter.end(),0);

      while(1){
        T f=dfs(s,t,lim);
        if(f==0) break;
        fl+=f;
        lim-=f;
      }
    }
    return fl;
  }

  T flow(ll s,ll t){
    return flow(s,t,numeric_limits<T>::max()/2);
  }

  T cut(ll s,ll t,ll x,ll a){
    static_assert(directed, "must be directed");
    auto &e=G[x][a];
    ll y=e.to;
    T ce=e.cap,cr=G[y][e.rev].cap;
    if(cr==0) return 0;
    e.cap=G[y][e.rev].cap=0;
    T cap=cr-flow(x,y,cr);
    if(x!=s&&cap!=0) flow(x,s,cap);
    if(t!=y&&cap!=0) flow(t,y,cap);
    e.cap=ce+cr;
    return cap;
  }
};
//END CUT HERE

template<typename T>
vector<T> compress(vector<T> v){
  sort(v.begin(),v.end());
  v.erase(unique(v.begin(),v.end()),v.end());
  return v;
}

template<typename T>
map<T, ll> dict(const vector<T> &v){
  map<T, ll> res;
  for(ll i=0;i<(ll)v.size();i++)
    res[v[i]]=i;
  return res;
}

int main(){
  ll i,j;
  ll n,m;cin>>n;
  vector<ll>a(n),b(n),c(n),d(n);
  for(i=0;i<n;i++)cin>>a[i]>>b[i];
  for(i=0;i<n;i++)cin>>c[i]>>d[i];
  Dinic<ll, true> dinic(2*n+2);
  for(i=0;i<n;i++)
  for(j=0;j<n;j++){
    if(a[i]<c[j]&&b[i]<d[j]){
      dinic.add_edge(i+1,n+j+1,1);
    }
  }
  for(i=0;i<n;i++)dinic.add_edge(0,i+1,1);
  for(i=0;i<n;i++)dinic.add_edge(n+i+1,2*n+1,1);
  cout<<dinic.flow(0,2*n+1)<<endl;
  return 0;
}

Measured memory_bytes: 512