#include <cassert>
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <functional>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef __int128 LL;
//typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef pair<int, int> PII;
std::ostream&
operator<<( std::ostream& dest, __int128_t value )
{
    std::ostream::sentry s( dest );
    if ( s ) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[ 128 ];
        char* d = std::end( buffer );
        do
        {
            -- d;
            *d = "0123456789"[ tmp % 10 ];
            tmp /= 10;
        } while ( tmp != 0 );
        if ( value < 0 ) {
            -- d;
            *d = '-';
        }
        int len = std::end( buffer ) - d;
        if ( dest.rdbuf()->sputn( d, len ) != len ) {
            dest.setstate( std::ios_base::badbit );
        }
    }
    return dest;
}

#define debug(args...) {vector<string> _v = split(#args, ','); err(_v.begin(), args); puts("");}
vector<string> split(const string& s, char c) {vector<string> v; stringstream ss(s); string x; while (getline(ss, x, c)) v.push_back(x); return v;}
void err(vector<string>::iterator it) {}
template<typename T, typename... Args> void err(vector<string>::iterator it, T a, Args... args) {cerr << it -> substr((*it)[0] == ' ', it -> length()) << " = " << a << ", "; err(++it, args...);}

#if (( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
#define lld I64d
#else
#define lld lld
#endif

#define all(x)  (x).begin(),(x).end()
#define tr(c, it)   for(auto it=c.begin(); it!=c.end(); it++)
#define clr(a, b)   memset(a, b, sizeof(a))
#define forn(i, n)   for(int i=0; i<n; i++)

const LL INF = 0x3f3f3f3f3f3f3f3fll;

vector<pair<int, int> > red, blue;
int n;


const int XMAX = 110,YMAX = 110;
const int EDGE_MAX = XMAX*YMAX;

struct E{
    int v, next;
}edge[EDGE_MAX];

int vis[XMAX], mat[YMAX];
int head[XMAX],e;

bool dfs(int x)
{
    vis[x] = 1;
    for(int i=head[x]; ~i; i=edge[i].next)
    {
        int y = edge[i].v;
        if(vis[mat[y]])  continue;
        if(!mat[y] || dfs(mat[y]))
        {
            mat[y] = x;
            return true;
        }
    }
    return false;
}

int hungary(int n)
{
    int ans = 0;
    clr(mat,0);
    for(int i=1; i<=n; i++)
    {
        clr(vis,0);
        if(dfs(i))  ans++;
    }
    return ans;
}

void addedge(int u,int v)
{
    edge[++e].v = v,edge[e].next = head[u];
    head[u] = e;
}



int main()
{
#ifdef LOCAL
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif

    while(cin >> n)
    {
        red.clear();
        blue.clear();
        clr(head, -1), e = 0;

        for(int i=1; i<=n; i++)
        {
            int x, y;
            cin >> x >> y;
            red.push_back({x, y});
        }
        for(int i=1; i<=n; i++)
        {
            int x, y;
            cin >> x >> y;
            blue.push_back({x, y});
        }

        //sort(red.begin(), red.end());
        //sort(blue.begin(), blue.end());

        //clr(vis, 0);

        //int ans = 0;
        for(int i=0; i<n; i++)
        {
            int bx = blue[i].first;
            int by = blue[i].second;

            for(int j=0; j<n; j++)
            {
                //if(vis[j])
                    //continue;

                int rx = red[j].first;
                int ry = red[j].second;

                if(rx < bx && ry < by)
                {
                    addedge(i+1, j+1);
                }
            }

        }

        int ans = hungary(n);
        cout << ans << endl;
    }


    return 0;
}

Measured memory_bytes: 256