// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
	vector<int> PensForLock;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	~PenSet();
	vector<int> CandidatesForBeauty(int);
	int findCapForBeauty(int, vector<int>);
	int findPenForBeauty(int);
	int findPenForLock(int);
	void getCountOfLockedAndBeautyPens();
	void getCountOfAllLockedPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

PenSet::~PenSet()
{
	delete[] pen;
	delete[] cap;
}

vector<int> PenSet::CandidatesForBeauty(int x)
{
	vector<int> v;

	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			v.push_back(i);

	return v;
}

int PenSet::findCapForBeauty(int x, vector<int> v)
{
	vector<int>::iterator it=v.begin();
	for(; it!=v.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	return -1;
}

int PenSet::findPenForBeauty(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].col == cap[x].col) )
			return i;

	return -1;
}

int PenSet::findPenForLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

void PenSet::getCountOfLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			vector<int> v = CandidatesForBeauty(i);

			if( !v.empty() )
			{
				int NumOfBeauty = findCapForBeauty(i,v);

				if ( NumOfBeauty!=-1 )
				{
					countOfLocked++;
					countOfBeauty++;
					pen[i].is_locked = true;
					cap[NumOfBeauty].is_locked = true;
				}
				else
					while( !v.empty() )
					{
						int NumOfV = findPenForBeauty(v.back());

						if( NumOfV!=-1 )
						{
							countOfLocked++;
							countOfBeauty++;
							pen[NumOfV].is_locked = true;
							cap[v.back()].is_locked = true;
						}
						else
						{
							int NumForLock = findPenForLock(v.back());

							if( NumForLock!=-1 )
							{
								countOfLocked++;
								pen[NumForLock].is_locked = true;
								cap[v.back()].is_locked = true;
							}
							else
								cap[v.back()].is_locked = true;
						}

						v.pop_back();
					}
			}
			else
				pen[i].is_locked = true;
		}
	}
}

void PenSet::getCountOfAllLockedPens()
{
	while( !PensForLock.empty() )
	{
		int NumForLock = PensForLock.back();
		PensForLock.pop_back();

		for(int j=0 ; j<m ; j++)
				if( !cap[j].is_locked && (cap[j].diam == pen[NumForLock].diam) )
				{
					pen[NumForLock].is_locked = true;
					cap[j].is_locked = true;
					countOfLocked++;
					break;
				}
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.getCountOfLockedAndBeautyPens();
	//PS1.getCountOfAllLockedPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
	vector<int> PensForLock;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	~PenSet();
	vector<int> CandidatesForBeauty(int);
	int findCapForBeauty(int, vector<int>);
	void getCountOfLockedAndBeautyPens();
	void getCountOfAllLockedPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

PenSet::~PenSet()
{
	delete[] pen;
	delete[] cap;
}

vector<int> PenSet::CandidatesForBeauty(int x)
{
	vector<int> v;

	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			v.push_back(i);

	return v;
}

int PenSet::findCapForBeauty(int x, vector<int> v)
{
	vector<int>::iterator it=v.begin();
	for(; it!=v.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	if( it == v.end() )
		return -1;
}

void PenSet::getCountOfLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			vector<int> v = CandidatesForBeauty(i);

			if( !v.empty() )
			{
				int NumOfBeauty = findCapForBeauty(i,v);

				if ( NumOfBeauty!=-1 )
				{
					countOfLocked++;
					countOfBeauty++;
					pen[i].is_locked = true;
					cap[NumOfBeauty].is_locked = true;
				}
				else
					PensForLock.push_back(i);

				v.clear();
			}
			else
				pen[i].is_locked = true;
		}
	}
}

void PenSet::getCountOfAllLockedPens()
{
	while( !PensForLock.empty() )
	{
		int NumForLock = PensForLock.back();
		PensForLock.pop_back();

		for(int j=0 ; j<m ; j++)
				if( !cap[j].is_locked && (cap[j].diam == pen[NumForLock].diam) )
				{
					pen[NumForLock].is_locked = true;
					cap[j].is_locked = true;
					countOfLocked++;
					break;
				}
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.getCountOfLockedAndBeautyPens();
	PS1.getCountOfAllLockedPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
using namespace std;

int a[1001][1001];
int n;
int m;
int CountOfLocked;
int CountOfBeauty;
int col, diam;
int MaxCol, MaxDiam;

void PrintMatrix()
{
	for(int i=1 ; i<=MaxCol ; i++)
	{
		for(int j=1 ; j<=MaxDiam ; j++)
			cout<<a[i][j]<<' ';
		cout<<endl;
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	cin>>n>>m;
	for(int i=0 ; i<n ; i++)
	{
		cin>>col>>diam;
		a[col][diam]++;
		if( col>MaxCol)
			MaxCol = col;
		if( diam>MaxDiam )
			MaxDiam = diam;
	}

	//PrintMatrix(); cout<<endl;

	for(int i=0 ; i<m ; i++)
	{
		cin>>col>>diam;
		if( a[col][diam]>0 )
		{
			CountOfBeauty++;
			CountOfLocked++;
		}

		a[col][diam]--;

		if( col>MaxCol)
			MaxCol = col;
		if( diam>MaxDiam )
			MaxDiam = diam;
	}

	//PrintMatrix(); cout<<endl;

	int SumOfPens;
	int SumOfCaps;
	for(int diam=1 ; diam<=MaxDiam ; diam++)
	{
		SumOfPens = 0;
		SumOfCaps = 0;
		for(int col=1 ; col<=MaxCol ; col++)
		{
			if(a[col][diam])
				if( a[col][diam] > 0 )
					SumOfPens+=a[col][diam];
				else
					SumOfCaps+=(-1)*a[col][diam];
		}
		CountOfLocked+=min(SumOfPens, SumOfCaps);
	}

	cout<<CountOfLocked<<' '<<CountOfBeauty<<endl;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
	vector<int> CandidatesOfCapsForLockPenBeauty;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	~PenSet();
	void findCandidatesOfCapsForLockPenBeauty(int);
	void analyseCandidatesOfCapsForBeautyAndLock();
	int findCapForBeautyAndLock(int);
	int findPenForBeautyAndLock(int);
	int findPenForLock(int);
	void lockPenAndCapBeauty(int,int);
	void lockPenAndCap(int,int);
	void CountLockedAndBeautyPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

PenSet::~PenSet()
{
	delete[] pen;
	delete[] cap;
}

void PenSet::findCandidatesOfCapsForLockPenBeauty(int x)
{
	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			CandidatesOfCapsForLockPenBeauty.push_back(i);
}

int PenSet::findCapForBeautyAndLock(int x)
{
	vector<int>::iterator it = CandidatesOfCapsForLockPenBeauty.begin();
	for(; it!=CandidatesOfCapsForLockPenBeauty.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	return -1;
}

int PenSet::findPenForBeautyAndLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].col == cap[x].col) && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

int PenSet::findPenForLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

void PenSet::lockPenAndCapBeauty(int i, int j)
{
	countOfLocked++;
	countOfBeauty++;
	pen[i].is_locked = true;
	cap[j].is_locked = true;
}

void PenSet::lockPenAndCap(int i, int j)
{
	countOfLocked++;
	pen[i].is_locked = true;
	cap[j].is_locked = true;
}

void PenSet::analyseCandidatesOfCapsForBeautyAndLock()
{
	while( !CandidatesOfCapsForLockPenBeauty.empty() )
	{
		int CandidateOfCaps = CandidatesOfCapsForLockPenBeauty.back();
		int NumOfPenForBeautyAndLock = findPenForBeautyAndLock(CandidateOfCaps);

		if( NumOfPenForBeautyAndLock!=-1 )
			lockPenAndCapBeauty( NumOfPenForBeautyAndLock, CandidateOfCaps );
		else
		{
			int NumForLock = findPenForLock(CandidateOfCaps);

			if( NumForLock!=-1 )
				lockPenAndCap( NumForLock, CandidateOfCaps );
			else
				cap[CandidateOfCaps].is_locked = true;
		}

		CandidatesOfCapsForLockPenBeauty.pop_back();
	}
}

void PenSet::CountLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			findCandidatesOfCapsForLockPenBeauty(i);

			if( !CandidatesOfCapsForLockPenBeauty.empty() )
			{
				int NumOfCapForBeautyAndLock = findCapForBeautyAndLock(i);

				if ( NumOfCapForBeautyAndLock!=-1 )
				{
					lockPenAndCapBeauty( i, NumOfCapForBeautyAndLock );
					CandidatesOfCapsForLockPenBeauty.clear();
				}
				else
					analyseCandidatesOfCapsForBeautyAndLock();
			}
			else
				pen[i].is_locked = true;
		}
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.CountLockedAndBeautyPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	vector<int> findCandidatesForBeauty(int);
	int findCapForBeauty(int, vector<int>);
	void getCountOfLockedAndBeautyPens();
	void getCountOfAllLockedPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

vector<int> PenSet::findCandidatesForBeauty(int x)
{
	vector<int> v;
	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			v.push_back(i);
	return v;
}

int PenSet::findCapForBeauty(int x, vector<int> v)
{
	vector<int>::iterator it=v.begin();
	for(; it!=v.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;
	if( it == v.end() )
		return 0;
}

void PenSet::getCountOfLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			vector<int> v = findCandidatesForBeauty(i);

			if( !v.empty() )
			{
				int NumOfBeauty = findCapForBeauty(i,v);
				if ( NumOfBeauty )
				{
					countOfLocked++;
					countOfBeauty++;
					pen[i].is_locked = true;
					cap[NumOfBeauty].is_locked = true;
				}
			}
			v.clear();
		}
	}
}

void PenSet::getCountOfAllLockedPens()
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked )
		{
			for(int j=0 ; j<m ; j++)
				if( !cap[j].is_locked && (cap[j].diam == pen[i].diam) )
				{
					pen[i].is_locked = true;
					cap[j].is_locked = true;
					countOfLocked++;
					break;
				}
		}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.getCountOfLockedAndBeautyPens();
	PS1.getCountOfAllLockedPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
	vector<int> CandidatesOfCapsForLockPenBeauty;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	~PenSet();
	void findCandidatesOfCapsForLockPenBeauty(int);
	void analyseCandidatesOfCapsForBeautyAndLock();
	int findCapForBeautyAndLock(int);
	int findPenForBeautyAndLock(int);
	int findPenForLock(int);
	void lockPenAndCapBeauty(int,int);
	void lockPenAndCap(int,int);
	void CountLockedAndBeautyPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

PenSet::~PenSet()
{
	delete[] pen;
	delete[] cap;
}

void PenSet::findCandidatesOfCapsForLockPenBeauty(int x)
{
	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			CandidatesOfCapsForLockPenBeauty.push_back(i);
}

int PenSet::findCapForBeautyAndLock(int x)
{
	vector<int>::iterator it = CandidatesOfCapsForLockPenBeauty.begin();
	for(; it!=CandidatesOfCapsForLockPenBeauty.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	return -1;
}

int PenSet::findPenForBeautyAndLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].col == cap[x].col) && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

int PenSet::findPenForLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

void PenSet::lockPenAndCapBeauty(int i, int j)
{
	countOfLocked++;
	countOfBeauty++;
	pen[i].is_locked = true;
	cap[j].is_locked = true;
}

void PenSet::lockPenAndCap(int i, int j)
{
	countOfLocked++;
	pen[i].is_locked = true;
	cap[j].is_locked = true;
}

void PenSet::analyseCandidatesOfCapsForBeautyAndLock()
{
	while( !CandidatesOfCapsForLockPenBeauty.empty() )
	{
		int CandidateOfCaps = CandidatesOfCapsForLockPenBeauty.back();
		int NumOfPenForBeautyAndLock = findPenForBeautyAndLock(CandidateOfCaps);

		if( NumOfPenForBeautyAndLock!=-1 )
			lockPenAndCapBeauty( NumOfPenForBeautyAndLock, CandidateOfCaps );
		else
		{
			int NumForLock = findPenForLock(CandidateOfCaps);

			if( NumForLock!=-1 )
				lockPenAndCap( NumForLock, CandidateOfCaps );
			else
				cap[CandidateOfCaps].is_locked = true;
		}

		CandidatesOfCapsForLockPenBeauty.pop_back();
	}
}

void PenSet::CountLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			findCandidatesOfCapsForLockPenBeauty(i);

			if( !CandidatesOfCapsForLockPenBeauty.empty() )
			{
				int NumOfCapForBeautyAndLock = findCapForBeautyAndLock(i);

				if ( NumOfCapForBeautyAndLock!=-1 )
					lockPenAndCapBeauty( i, NumOfCapForBeautyAndLock );
				else
					analyseCandidatesOfCapsForBeautyAndLock();
			}
			else
				pen[i].is_locked = true;
		}
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.CountLockedAndBeautyPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
	vector<int> PensForLock;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	~PenSet();
	vector<int> CandidatesForBeauty(int);
	int findCapForBeauty(int, vector<int>);
	int findPenForBeauty(int);
	int findPenForLock(int);
	void getCountOfLockedAndBeautyPens();
	void getCountOfAllLockedPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

PenSet::~PenSet()
{
	delete[] pen;
	delete[] cap;
}

vector<int> PenSet::CandidatesForBeauty(int x)
{
	vector<int> v;

	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			v.push_back(i);

	return v;
}

int PenSet::findCapForBeauty(int x, vector<int> v)
{
	vector<int>::iterator it=v.begin();
	for(; it!=v.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	return -1;
}

int PenSet::findPenForBeauty(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].col == cap[x].col) && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

int PenSet::findPenForLock(int x)
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked && (pen[i].diam == cap[x].diam) )
			return i;

	return -1;
}

void PenSet::getCountOfLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			vector<int> v = CandidatesForBeauty(i);

			if( !v.empty() )
			{
				int NumOfBeauty = findCapForBeauty(i,v);

				if ( NumOfBeauty!=-1 )
				{
					countOfLocked++;
					countOfBeauty++;
					pen[i].is_locked = true;
					cap[NumOfBeauty].is_locked = true;
				}
				else
					while( !v.empty() )
					{
						int NumOfV = findPenForBeauty(v.back());

						if( NumOfV!=-1 )
						{
							countOfLocked++;
							countOfBeauty++;
							pen[NumOfV].is_locked = true;
							cap[v.back()].is_locked = true;
						}
						else
						{
							int NumForLock = findPenForLock(v.back());

							if( NumForLock!=-1 )
							{
								countOfLocked++;
								pen[NumForLock].is_locked = true;
								cap[v.back()].is_locked = true;
							}
							else
								cap[v.back()].is_locked = true;
						}

						v.pop_back();
					}
			}
			else
				pen[i].is_locked = true;
		}
	}
}

void PenSet::getCountOfAllLockedPens()
{
	while( !PensForLock.empty() )
	{
		int NumForLock = PensForLock.back();
		PensForLock.pop_back();

		for(int j=0 ; j<m ; j++)
				if( !cap[j].is_locked && (cap[j].diam == pen[NumForLock].diam) )
				{
					pen[NumForLock].is_locked = true;
					cap[j].is_locked = true;
					countOfLocked++;
					break;
				}
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.getCountOfLockedAndBeautyPens();
	//PS1.getCountOfAllLockedPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
using namespace std;

int a[1001][1001];
int n;
int m;
int CountOfLocked;
int CountOfBeauty;
int col, diam;
int MaxCol, MaxDiam;

void PrintMatrix()
{
	for(int i=1 ; i<=MaxCol ; i++)
	{
		for(int j=1 ; j<=MaxDiam ; j++)
			cout<<a[i][j]<<' ';
		cout<<endl;
	}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);

	cin>>n>>m;
	for(int i=0 ; i<n ; i++)
	{
		cin>>col>>diam;
		a[col][diam]++;
		if( col>MaxCol)
			MaxCol = col;
		if( diam>MaxDiam )
			MaxDiam = diam;
	}

	//PrintMatrix(); cout<<endl;

	for(int i=0 ; i<m ; i++)
	{
		cin>>col>>diam;
		if( a[col][diam] )
		{
			CountOfBeauty++;
			CountOfLocked++;
		}

		a[col][diam]--;

		if( col>MaxCol)
			MaxCol = col;
		if( diam>MaxDiam )
			MaxDiam = diam;
	}

	//PrintMatrix(); cout<<endl;

	int SumOfPens;
	int SumOfCaps;
	for(int diam=1 ; diam<=MaxDiam ; diam++)
	{
		SumOfPens = 0;
		SumOfCaps = 0;
		for(int col=1 ; col<=MaxCol ; col++)
		{
			if(a[col][diam])
				if( a[col][diam] > 0 )
					SumOfPens+=a[col][diam];
				else
					SumOfCaps+=(-1)*a[col][diam];
		}
		CountOfLocked+=min(SumOfPens, SumOfCaps);
	}

	cout<<CountOfLocked<<' '<<CountOfBeauty<<endl;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


// VK_Cup_2-2.cpp: определяет точку входа для консольного приложения.
//

#include <iostream>
#include <vector>
using namespace std;

struct Data {
	int diam;
	int col;
	bool is_locked;
	Data(){}
};

class PenSet {
	Data *pen;
	Data *cap;
	int n;
	int m;
public:
	int countOfLocked;
	int countOfBeauty;
	PenSet();
	vector<int> CandidatesForBeauty(int);
	int findCapForBeauty(int, vector<int>);
	void getCountOfLockedAndBeautyPens();
	void getCountOfAllLockedPens();
};

PenSet::PenSet()
{
	cin>>n>>m;
	pen = new Data[n];
	for(int i=0 ; i<n ; i++)
	{
		cin>>pen[i].col;
		cin>>pen[i].diam;
		pen[i].is_locked = false;
	}

	cap = new Data[m];
	for(int i=0 ; i<m ; i++)
	{
		cin>>cap[i].col;
		cin>>cap[i].diam;
		cap[i].is_locked = false;
	}

	countOfLocked = 0;
	countOfBeauty = 0;
}

vector<int> PenSet::CandidatesForBeauty(int x)
{
	vector<int> v;

	for(int i=0 ; i<m ; i++)
		if( !cap[i].is_locked && (pen[x].diam == cap[i].diam) )
			v.push_back(i);

	return v;
}

int PenSet::findCapForBeauty(int x, vector<int> v)
{
	vector<int>::iterator it=v.begin();
	for(; it!=v.end() ; it++)
		if( pen[x].col == cap[(*it)].col )
			return *it;

	if( it == v.end() )
		return -1;
}

void PenSet::getCountOfLockedAndBeautyPens()
{
	for(int i=0 ; i<n ; i++)
	{
		if( !pen[i].is_locked )
		{
			vector<int> v = CandidatesForBeauty(i);

			if( !v.empty() )
			{
				int NumOfBeauty = findCapForBeauty(i,v);

				if ( NumOfBeauty!=-1 )
				{
					countOfLocked++;
					countOfBeauty++;
					pen[i].is_locked = true;
					cap[NumOfBeauty].is_locked = true;
				}

				v.clear();
			}
			else
				pen[i].is_locked = true;
		}
	}
}

void PenSet::getCountOfAllLockedPens()
{
	for(int i=0 ; i<n ; i++)
		if( !pen[i].is_locked )
		{
			for(int j=0 ; j<m ; j++)
				if( !cap[j].is_locked && (cap[j].diam == pen[i].diam) )
				{
					pen[i].is_locked = true;
					cap[j].is_locked = true;
					countOfLocked++;
					break;
				}
		}
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	PenSet PS1;
	PS1.getCountOfLockedAndBeautyPens();
	PS1.getCountOfAllLockedPens();
	cout<<PS1.countOfLocked<<' '<<PS1.countOfBeauty;
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>

#define f first
#define s second
#define mp make_pair

using namespace std;

int main()
{
        int n, m, i, j, ans1=0, ans2=0, L=0, k=0, N=0;
        cin >> n >> m;
        multiset <pair <int, int> > st, st1;
        for (i=0; i<n; i++)
        {
            int x, y;
            cin >> x >> y;
            st.insert(mp(y,x));
        }
        for (i=0; i<m; i++)
        {
            int x, y;
            cin >> x >> y;
            st1.insert(mp(y,x));
        }
        vector <pair <int, int> > f(st.begin(), st.end()), q(st1.begin(), st1.end());
        for (i=0; i<n && L<m; i=j)
        {
            vector <int> v(1001,0);
            for (j=i+1, v[f[i].s]=1; j<n; j++)
            {
                if (f[i].f != f[j].f) break;
                v[f[j].s]++;
            }
            for (k=0; L<m; L++)
            {
                if (q[L].f > f[i].f) break;
                if (q[L].f == f[i].f)
                {
                    k++;
                    if (v[q[L].s] > 0)
                    {
                        ans2++;
                        v[q[L].s]--;
//                        cout << ans2 << endl;
                    }
                }
            }
/*            for (j=0; j<n; j++)
            cout << v[j] << " ";
            cout << endl;  */
            if (k > j-i) ans1+=j-i; else ans1+=k;
        }
    cout << ans1 << " " << ans2 << endl;
//    system("pause");
    return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>

#define f first
#define s second
#define mp make_pair

using namespace std;

int main()
{
        int n, m, i, j, ans1=0, ans2=0, L=0, k=0, N=0;
        cin >> n >> m;
        multiset <pair <int, int> > st, st1;
        for (i=0; i<n; i++)
        {
            int x, y;
            cin >> x >> y;
            st.insert(mp(y,x));
        }
        for (i=0; i<m; i++)
        {
            int x, y;
            cin >> x >> y;
            st1.insert(mp(y,x));
        }
        vector <pair <int, int> > f(st.begin(), st.end()), q(st1.begin(), st1.end());
        for (i=0; i<n && L<m; i++)
        {
            vector <int> v(1001,0);
            for (j=i+1, v[f[i].s]=1; j<n; j++)
            {
                if (f[i].f != f[j].f) break;
                v[f[j].s]++;
            }
            for (k=0; L<m; L++)
            {
                if (q[L].f > f[i].f) break;
                if (q[L].f == f[i].f)
                {
                    k++;
                    if (v[q[L].s] > 0)
                    {
                        ans2++;
                        v[q[L].s]--;
//                        cout << ans2 << endl;
                    }
                }
            }
/*            for (j=0; j<n; j++)
            cout << v[j] << " ";
            cout << endl;  */
            if (k > j-i) ans1+=j-i; else ans1+=k;
        }
    cout << ans1 << " " << ans2 << endl;
//    system("pause");
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<iterator>
#include<cmath>
#include<string>
#include<sstream>
#include<cstring>
#include<ctype.h>
#include<iomanip>
#include<bitset>
#include<stdio.h>
#include<fstream>
#include<regex>
#include<stdlib.h>
#include<math.h>

using namespace std;

#define all(v)         v.begin(),v.end()
#define sz(v)        ((int)((v).size()))
#define psh(x)               push_back(x)
#define mk(x,y)           make_pair(x,y)
#define ck(a)               (a<1 || a>9)
#define lop(i,n)     for(ll i=0;i<n;i++)
#define loop(i,f,l)  for(ll i=f;i<l;i++)
#define READ(s)   freopen(s, "r", stdin)
#define WRITE(s) freopen(s, "w", stdout)
#define scl(n)          scanf("%lld",&n)
#define sc(n)             scanf("%d",&n)
#define INF                   1000000000
#define LINF               1000000000000
#define PI             3.141592653589793

typedef long long           ll;
typedef pair <int, int>     ii;
typedef pair<double, double>dd;
typedef pair<string, int>   si;
typedef pair<int, string>   is;
typedef pair<char, int>    chi;
typedef vector<ii>         vii;
typedef vector<int>         vi;
typedef vector<vi>         vvi;
typedef vector<string>      vs;
typedef vector<ll>         vll;
typedef vector<vii>       vvii;
typedef set<int>           sti;

const double EPS = (1e-7);

int dx[] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dy[] = { 0, 0, -1, 1, 1, -1, 1, -1 };

int gcd(int a, int b) { return (b == 0 ? a : gcd(b, a % b)); }
int lcm(int a, int b) { return ((a*b) / gcd(a, b)); }
ll pw(ll b, ll p){ if (!p) return 1; ll sq = pw(b, p / 2); sq *= sq; if (p % 2) sq *= b; return sq; }
int sd(ll x){ return x<10 ? x : x % 10 + sd(x / 10); }
ll sq(ll x){ lop(i, x)if ((ll)i*i > x) return (i - 1); return ll(1); }
//READ("input.txt");WRITE("output.txt");

int main()
{
    int n, m,ans=0,b=0; cin >> n >> m;
    vii marker(n);
    lop(i, n)   cin >> marker[i].first >> marker[i].second;
    vector < pair<int, vector<int> >  > cap(1005);
    lop(i, m)   { int x, y; cin >> x >> y; cap[y].first = 1, cap[y].second.push_back(x); }
    lop(i, sz(marker))
    {
        if (cap[marker[i].second].first && find(cap[marker[i].second].second.begin(), cap[marker[i].second].second.end(), marker[i].first) != cap[marker[i].second].second.end())
        {
            ans++, b++;
            cap[marker[i].second].second.erase(find(cap[marker[i].second].second.begin(), cap[marker[i].second].second.end(), marker[i].first));
            if (cap[marker[i].second].second.empty()) cap[marker[i].second].first = 0;
            marker.erase(marker.begin() + i);
            i--;
        }
    }
    lop(i, sz(marker))
    {
        if (cap[marker[i].second].first)
        {
            ans++;
            cap[marker[i].second].second.erase(cap[marker[i].second].second.begin());
            if (cap[marker[i].second].second.empty()) cap[marker[i].second].first = 0;
        }
    }
    cout << ans << ' ' << b;
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<iterator>
#include<cmath>
#include<string>
#include<sstream>
#include<cstring>
#include<ctype.h>
#include<iomanip>
#include<bitset>
#include<stdio.h>
#include<fstream>
#include<regex>
#include<stdlib.h>
#include<math.h>

using namespace std;

#define all(v)         v.begin(),v.end()
#define sz(v)        ((int)((v).size()))
#define psh(x)               push_back(x)
#define mk(x,y)           make_pair(x,y)
#define ck(a)               (a<1 || a>9)
#define lop(i,n)     for(ll i=0;i<n;i++)
#define loop(i,f,l)  for(ll i=f;i<l;i++)
#define READ(s)   freopen(s, "r", stdin)
#define WRITE(s) freopen(s, "w", stdout)
#define scl(n)          scanf("%lld",&n)
#define sc(n)             scanf("%d",&n)
#define INF                   1000000000
#define LINF               1000000000000
#define PI             3.141592653589793

typedef long long           ll;
typedef pair <int, int>     ii;
typedef pair<double, double>dd;
typedef pair<string, int>   si;
typedef pair<int, string>   is;
typedef pair<char, int>    chi;
typedef vector<ii>         vii;
typedef vector<int>         vi;
typedef vector<vi>         vvi;
typedef vector<string>      vs;
typedef vector<ll>         vll;
typedef vector<vii>       vvii;
typedef set<int>           sti;

const double EPS = (1e-7);

int dx[] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dy[] = { 0, 0, -1, 1, 1, -1, 1, -1 };

int gcd(int a, int b) { return (b == 0 ? a : gcd(b, a % b)); }
int lcm(int a, int b) { return ((a*b) / gcd(a, b)); }
ll pw(ll b, ll p){ if (!p) return 1; ll sq = pw(b, p / 2); sq *= sq; if (p % 2) sq *= b; return sq; }
int sd(ll x){ return x<10 ? x : x % 10 + sd(x / 10); }
ll sq(ll x){ lop(i, x)if ((ll)i*i > x) return (i - 1); return ll(1); }
//READ("input.txt");WRITE("output.txt");

int main()
{
    int n, m,ans=0,b=0; cin >> n >> m;
    vector<pair<ii,int> > marker(n);
    lop(i, n)   cin >> marker[i].first.first >> marker[i].first.second;
    vector < pair<int, vector<int> >  > cap(1005);
    lop(i, m)   { int x, y; cin >> x >> y; cap[y].first++, cap[y].second.push_back(x); }
    lop(i, n)
    {
        int d = marker[i].first.second, c = marker[i].first.first;
        if (cap[marker[i].first.second].first)
        {
            vi::iterator it = find(cap[d].second.begin(), cap[d].second.begin() + cap[d].first, c);
            if (it != cap[d].second.begin() + cap[d].first)
            {
                marker[i].second = 1;
                ans++, b++;
                swap(cap[d].second[it - cap[d].second.begin()], cap[d].second[cap[d].first - 1]);
                cap[d].first--;
            }
        }
    }
    lop(i, n)
    {
        int d = marker[i].first.second;
        if (!marker[i].second && cap[d].first)
        {
            ans++;
            cap[d].first--;
        }
    }
    cout << ans << ' ' << b;
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<iterator>
#include<cmath>
#include<string>
#include<sstream>
#include<cstring>
#include<ctype.h>
#include<iomanip>
#include<bitset>
#include<stdio.h>
#include<fstream>
#include<regex>
#include<stdlib.h>
#include<math.h>

using namespace std;

#define all(v)         v.begin(),v.end()
#define sz(v)        ((int)((v).size()))
#define psh(x)               push_back(x)
#define mk(x,y)           make_pair(x,y)
#define ck(a)               (a<1 || a>9)
#define lop(i,n)     for(ll i=0;i<n;i++)
#define loop(i,f,l)  for(ll i=f;i<l;i++)
#define READ(s)   freopen(s, "r", stdin)
#define WRITE(s) freopen(s, "w", stdout)
#define scl(n)          scanf("%lld",&n)
#define sc(n)             scanf("%d",&n)
#define INF                   1000000000
#define LINF               1000000000000
#define PI             3.141592653589793

typedef long long           ll;
typedef pair <int, int>     ii;
typedef pair<double, double>dd;
typedef pair<string, int>   si;
typedef pair<int, string>   is;
typedef pair<char, int>    chi;
typedef vector<ii>         vii;
typedef vector<int>         vi;
typedef vector<vi>         vvi;
typedef vector<string>      vs;
typedef vector<ll>         vll;
typedef vector<vii>       vvii;
typedef set<int>           sti;

const double EPS = (1e-7);

int dx[] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dy[] = { 0, 0, -1, 1, 1, -1, 1, -1 };

int gcd(int a, int b) { return (b == 0 ? a : gcd(b, a % b)); }
int lcm(int a, int b) { return ((a*b) / gcd(a, b)); }
ll pw(ll b, ll p){ if (!p) return 1; ll sq = pw(b, p / 2); sq *= sq; if (p % 2) sq *= b; return sq; }
int sd(ll x){ return x<10 ? x : x % 10 + sd(x / 10); }
ll sq(ll x){ lop(i, x)if ((ll)i*i > x) return (i - 1); return ll(1); }
//READ("input.txt");WRITE("output.txt");

int main()
{
    int n, m,ans=0,b=0; cin >> n >> m;
    vii marker(n);
    lop(i, n)   cin >> marker[i].first >> marker[i].second;
    vector < pair<int, vector<int> >  > cap(1005);
    lop(i, m)   { int x, y; cin >> x >> y; cap[y].first++, cap[y].second.push_back(x); }
    lop(i, sz(marker))
    {
        vi::iterator it = find(cap[marker[i].second].second.begin(), cap[marker[i].second].second.begin()+cap[marker[i].second].first, marker[i].first);
        if (cap[marker[i].second].first && it != cap[marker[i].second].second.end())
        {
            ans++, b++;
            swap(cap[marker[i].second].second[it - cap[marker[i].second].second.begin()], cap[marker[i].second].second[cap[marker[i].second].first - 1]);
            cap[marker[i].second].first--;
            marker.erase(marker.begin() + i);
            i--;
        }
    }
    lop(i, sz(marker))
    {
        if (cap[marker[i].second].first)
        {
            ans++;
            cap[marker[i].second].first--;
        }
    }
    cout << ans << ' ' << b;
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<iterator>
#include<cmath>
#include<string>
#include<sstream>
#include<cstring>
#include<ctype.h>
#include<iomanip>
#include<bitset>
#include<stdio.h>
#include<fstream>
#include<regex>
#include<stdlib.h>
#include<math.h>

using namespace std;

#define all(v)         v.begin(),v.end()
#define sz(v)        ((int)((v).size()))
#define psh(x)               push_back(x)
#define mk(x,y)           make_pair(x,y)
#define ck(a)               (a<1 || a>9)
#define lop(i,n)     for(ll i=0;i<n;i++)
#define loop(i,f,l)  for(ll i=f;i<l;i++)
#define READ(s)   freopen(s, "r", stdin)
#define WRITE(s) freopen(s, "w", stdout)
#define scl(n)          scanf("%lld",&n)
#define sc(n)             scanf("%d",&n)
#define INF                   1000000000
#define LINF               1000000000000
#define PI             3.141592653589793

typedef long long           ll;
typedef pair <int, int>     ii;
typedef pair<double, double>dd;
typedef pair<string, int>   si;
typedef pair<int, string>   is;
typedef pair<char, int>    chi;
typedef vector<ii>         vii;
typedef vector<int>         vi;
typedef vector<vi>         vvi;
typedef vector<string>      vs;
typedef vector<ll>         vll;
typedef vector<vii>       vvii;
typedef set<int>           sti;

const double EPS = (1e-7);

int dx[] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int dy[] = { 0, 0, -1, 1, 1, -1, 1, -1 };

int gcd(int a, int b) { return (b == 0 ? a : gcd(b, a % b)); }
int lcm(int a, int b) { return ((a*b) / gcd(a, b)); }
ll pw(ll b, ll p){ if (!p) return 1; ll sq = pw(b, p / 2); sq *= sq; if (p % 2) sq *= b; return sq; }
int sd(ll x){ return x<10 ? x : x % 10 + sd(x / 10); }
ll sq(ll x){ lop(i, x)if ((ll)i*i > x) return (i - 1); return ll(1); }
//READ("input.txt");WRITE("output.txt");

int main()
{
    int n, m,ans=0,b=0; cin >> n >> m;
    vector<pair<ii,int> > marker(n);
    lop(i, n)   cin >> marker[i].first.first >> marker[i].first.second;
    vector < pair<int, vector<int> >  > cap(1005);
    lop(i, m)   { int x, y; cin >> x >> y; cap[y].first++, cap[y].second.push_back(x); }
    lop(i, sz(marker))
    {
        vi::iterator it = find(cap[marker[i].first.second].second.begin(), cap[marker[i].first.second].second.begin()+cap[marker[i].first.second].first, marker[i].first.first);
        if (cap[marker[i].first.second].first && it != cap[marker[i].first.second].second.end())
        {
            marker[i].second = 1;
            ans++, b++;
            swap(cap[marker[i].first.second].second[it - cap[marker[i].first.second].second.begin()], cap[marker[i].first.second].second[cap[marker[i].first.second].first - 1]);
            cap[marker[i].first.second].first--;
        }
    }
    lop(i, sz(marker))
    {
        if (!marker[i].second && cap[marker[i].first.second].first)
        {
            ans++;
            cap[marker[i].first.second].first--;
        }
    }
    cout << ans << ' ' << b;
    return 0;
}


#include <iostream>
using namespace std;

struct vect{
  int amount_kol;
  int amount_fl;
}base[1000000];

int
main(){

  int n,m,i,buf1,buf2, res1, res2,resbuf1, resbuf2;
  cin >> n >> m;
  for ( i = 0; i < 1000000; i++){
     base[i].amount_kol = base[i].amount_fl = 0;
  }
  for ( i = 0; i < n; i++){
      cin >> buf1 >> buf2;
      base[1000*(buf2-1)+buf1-1].amount_fl++;
  }
  for ( i = 0; i < m; i++){
      cin >> buf1 >> buf2;
      base[1000*(buf2-1)+buf1-1].amount_kol++;
  }
  resbuf1 = resbuf2 = res1 = res2 = 0;
  for ( i = 0; i < 1000000; i++){
     res2+= base[i].amount_fl < base[i].amount_kol ? base[i].amount_fl : base[i].amount_kol;
     resbuf1 += base[i].amount_fl;
     resbuf2 += base[i].amount_kol;
     if ( !((i+1)%1000)){
        res1+= resbuf1 < resbuf2 ? resbuf1 : resbuf2;
        resbuf1 = resbuf2 = 0;
     }
  }
  cout << res1 << ' ' << res2 << endl;
return 0;
}


#include <iostream>
using namespace std;

struct vect{
  int amount_kol;
  int amount_fl;
}base[1000000];

int
main(){

  int n,m,i,buf1,buf2, res1, res2,resbuf1, resbuf2;
  cin >> n >> m;
  for ( i = 0; i < 1000000; i++){
     base[i].amount_kol = base[i].amount_fl = 0;
  }
  for ( i = 0; i < n; i++){
      cin >> buf1 >> buf2;
      base[1000*(buf2-1)+buf1].amount_fl++;
  }
  for ( i = 0; i < m; i++){
      cin >> buf1 >> buf2;
      base[1000*(buf2-1)+buf1].amount_kol++;
  }
  resbuf1 = resbuf2 = res1 = res2 = 0;
  for ( i = 0; i < 1000000; i++){
     res2+= base[i].amount_fl < base[i].amount_kol ? base[i].amount_fl : base[i].amount_kol;
     resbuf1 += base[i].amount_fl;
     resbuf2 += base[i].amount_kol;
     if ( !((i+1)%1000)){
        res1+= resbuf1 < resbuf2 ? resbuf1 : resbuf2;
        resbuf1 = resbuf2 = 0;
     }
  }
  cout << res1 << ' ' << res2 << endl;
return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <sstream>

#define pb push_back
#define mp make_pair
#define PI 3.14159265358979
#define sqr(x) (x)*(x)
#define forn(i, n) for(int i = 0; i < n; ++i)
#define ALL(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define X first
#define Y second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
using namespace std;
typedef pair<int,int> pii;
const int INF = 2147483647;
const ll LLINF = 9223372036854775807LL;
const int maxn = 100010;
pii f[maxn], k[maxn];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) scanf("%d%d", &f[i].Y, &f[i].X);
    for (int i = 0; i < m; ++i) scanf("%d%d", &k[i].Y, &k[i].X);
    sort(f,f+n);
    sort(k,k+m);
    int l = 0;
    int r = 0;
    int u = 0, v = 0;
    vector<pii> vk, vf;
    while (l<n&&r<m) {
        if (f[l]==k[r]) {
            u++;v++;l++;r++;
        } else if (f[l]<k[r]) vf.pb(f[l]),l++;
        else vk.pb(k[r]),r++;
    }
    while (l<n) vf.pb(f[l++]);
    while (r<m) vk.pb(k[r++]);
    l = 0;
    r = 0;
    while (l<vf.size()&&r<vk.size()) {
        if (f[l].X==k[r].X) {
            u++;l++;r++;
        }else if (f[l].X<k[r].X) l++;
        else r++;
    }
    printf("%d %d\n", u, v);
    return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <sstream>

#define pb push_back
#define mp make_pair
#define PI 3.14159265358979
#define sqr(x) (x)*(x)
#define forn(i, n) for(int i = 0; i < n; ++i)
#define ALL(x) x.begin(), x.end()
#define sz(x) int((x).size())
#define X first
#define Y second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
using namespace std;
typedef pair<int,int> pii;
const int INF = 2147483647;
const ll LLINF = 9223372036854775807LL;
const int maxn = 100010;
pii f[maxn], k[maxn];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) scanf("%d%d", &f[i].Y, &f[i].X);
    for (int i = 0; i < m; ++i) scanf("%d%d", &k[i].Y, &k[i].X);
    sort(f,f+n);
    sort(k,k+m);
    int l = 0;
    int r = 0;
    int u = 0, v = 0;
    vector<pii> vk, vf;
    while (l<n&&r<m) {
        if (f[l]==k[r]) {
            u++;v++;l++;r++;
        } else if (f[l]<k[r]) vf.pb(f[l]),l++;
        else vk.pb(k[r]),r++;
    }
    while (l<n) vf.pb(f[l++]);
    while (r<m) vk.pb(k[r++]);
    l = 0;
    r = 0;
    while (l<vf.size()&&r<vk.size()) {
        if (vf[l].X==vk[r].X) {
            u++;l++;r++;
        }else if (vf[l].X<vk[r].X) l++;
        else r++;
    }
    printf("%d %d\n", u, v);
    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f, c;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		c.push_back(make_pair(b, a));
	}

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first && c[i].second == f[j].second && !ub[j] && !uc[i])
				{
					ub[j] = true;
					uc[i] = true;
					++beauty;
					++closed;
					break;
				}
			}

	for (int i = 0; i < m; ++i)
		if (!uc[i])
			for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first  && !ub[j])
				{
					ub[j] = true;
					++closed;
					break;
				}
			}
	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int f[1001][1001];
int r[1001];

int main()
{
    int n, m, a, b;
    cin >> n >> m;
    vector<int> col;
    for (int i = 0; i < n; ++i)
    {
        cin >> a >> b;
        ++f[a][b];
		++r[b];
    }
    int beauty = 0, closed = 0;
    for (int i = 0; i < m; ++i)
    {
        cin >> a >> b;
        if (f[a][b])
        {
            --f[a][b];
			--r[b];
            ++beauty;
            ++closed;
        }
        else
			col.push_back(b);
    }
	for (int i = 0 ; i < col.size(); ++i)
    {
		if (r[col[i]])
		{
			++closed;
			--r[col[i]];
		}
	}

    cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int f[1001][1001];

int main()
{
	memset(f, 0, sizeof(f));
	int n, m, a, b;
	cin >> n >> m;
	vector<int> col;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		++f[a][b];
	}
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		if (f[a][b])
		{
			--f[a][b];
			++beauty;
			++closed;
		}
		else
			col.push_back(b);
	}
	for (int i = 0; i < col.size(); ++i)
		for (int j = 1; j <= n; ++j)
			if (f[j][col[i]])
			{
				++closed;
				--f[j][col[i]];
				break;
			}

	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int fdd[100000];

	memset(fdd, -1, sizeof(fdd));
	fdd[f[0].first] = 0;
	for (int i = 1; i < n; ++i)
		if (f[i].first != f[i-1].first)
			fdd[f[i].first] = i;
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		if (fdd[b] != -1)
			for (int j = fdd[b]; j < n; ++j)
			{
				if (b == f[j].first && a == f[j].second && !ub[j])
				{
					ub[j] = true;
					++beauty;
				}
				if (b == f[j].first && !uc[j])
				{
					uc[j] = true;
					++closed;
				}
				if (b < f[j].first)
					break;
			}
	}

	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f, c;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		c.push_back(make_pair(b, a));
	}

	for (int i = 0; i < c.size(); ++i)
		for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first && c[i].second == f[j].second && !ub[j] && !uc[i])
				{
					ub[j] = true;
					c.erase(c.begin()+i, c.begin()+i+1);
					--i;
					++beauty;
					++closed;
					break;
				}
			}

	for (int i = 0; i < c.size(); ++i)
		if (!uc[i])
			for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first  && !ub[j])
				{
					ub[j] = true;
					++closed;
					break;
				}
			}
	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f, c;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		c.push_back(make_pair(b, a));
	}
	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first && c[i].second == f[j].second && !ub[j])
				{
					ub[j] = true;
					++beauty;
					++closed;
				}
			}

	for (int i = 0; i < m; ++i)
			for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first  && !ub[j])
				{
					ub[j] = true;
					++closed;
				}
			}
	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f, c;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int fdd[100000];

	memset(fdd, -1, sizeof(fdd));
	fdd[f[0].first] = 0;
	for (int i = 1; i < n; ++i)
		if (f[i].first != f[i-1].first)
			fdd[f[i].first] = i;
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		c.push_back(make_pair(b, a));
	}
	for (int i = 0; i < m; ++i)
		if (fdd[c[i].first] != -1)
		{
			for (int j = fdd[c[i].first]; j < n; ++j)
			{
				if (c[i].first == f[j].first && c[i].second == f[j].second && !ub[j])
				{
					ub[j] = true;
					++beauty;
					++closed;
				}
				if (c[i].first < f[j].first)
					break;
			}
		}

	for (int i = 0; i < m; ++i)
		if (fdd[c[i].first] != -1)
		{
			for (int j = fdd[c[i].first]; j < n; ++j)
			{
				if (c[i].first == f[j].first  && !ub[j])
				{
					ub[j] = true;
					++closed;
				}
				if (c[i].first < f[j].first)
					break;
			}
		}

	cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;

int f[1001][1001];
int r[1001];

int main()
{
    int n, m, a, b;
    cin >> n >> m;
    set<int> col;
    for (int i = 0; i < n; ++i)
    {
        cin >> a >> b;
        ++f[a][b];
    }
    int beauty = 0, closed = 0;
    for (int i = 0; i < m; ++i)
    {
        cin >> a >> b;
        if (f[a][b])
        {
            --f[a][b];
            ++beauty;
            ++closed;
        }
        else
        {
			col.insert(b);
			++r[b];
		}
    }
	for (set<int>::iterator i = col.begin(); i != col.end(); ++i)
    {
		int j = 0;
		while(r[*i] && j <= n)
        {
            closed += f[j][*i];
			r[*i] -= f[j][*i];
			++j;
        }
	}
    cout << closed << " " << beauty << endl;

    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool ub[100000], uc[100000];

int main()
{
	int n, m, a, b;
	cin >> n >> m;
	vector<pair<int, int>> f, c;
	for (int i = 0; i < n; ++i)
	{
		cin >> a >> b;
		f.push_back(make_pair(b, a));
	}

	sort(f.begin(), f.end());
	int beauty = 0, closed = 0;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		c.push_back(make_pair(b, a));
	}

	for (int i = 0; i < c.size(); ++i)
		for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first && c[i].second == f[j].second && !ub[j] && !uc[i])
				{
					ub[j] = true;
					c.erase(c.begin()+i, c.begin()+i);
					--i;
					++beauty;
					++closed;
					break;
				}
			}

	for (int i = 0; i < c.size(); ++i)
		if (!uc[i])
			for (int j = 0; j < n; ++j)
			{
				if (c[i].first == f[j].first  && !ub[j])
				{
					ub[j] = true;
					++closed;
					break;
				}
			}
	cout << closed << " " << beauty << endl;

    return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> VI;
typedef vector< vector<ll> > VVI;
typedef pair<ll, ll> PII;
typedef vector<ll> VPII;

#define REP(i, n) for(int i = 0; i < n; ++i)
#define RREP(i, n) for(int i = n - 1; i >= 0; --i)
#define FOR(i, x, y) for(int i = x; i <= y; ++i)
#define RFOR(i, x, y) for(int i = x; i >= y; --i)
#define SZ(a) (ll)(a).size()
#define ALL(a) (a).begin(),(a).end()
#define SORT(a) sort(ALL(a))
#define CLEAR(x) memset(x,0,sizeof x);
#define UNIQUE(c) SORT(c),(c).resize(unique(ALL(c))-(c).begin())
#define pb push_back
#define sqr(x) (x)*(x)
#define X first
#define Y second

const long double pi=acos(-1.0);
const long double eps = 1e-9;
const int INF = 1000000000;

int a[1024][1024];
int b[1024][1024];
int n, m;
int x, y;
int total, nice;

int main()
{
  cin >> n >> m;
  REP(i, n)
  {
    cin >> x >> y;
    ++a[x][y];
  }

  REP(i, m)
  {
    cin >> x >> y;
    ++b[x][y];
  }

  FOR(i, 1, 1000)
    FOR(j, 1, 1000)
    {
      int cur = min(a[i][j], b[i][j]);
      a[i][j] -= cur;
      b[i][j] -= cur;
      total += cur;
      nice += cur;
    }
  FOR(j, 1, 1000)
  {
    int c1 = 0;
    int c2 = 0;
    FOR(i, 1, 100)
    {
      c1 += a[i][j];
      c2 += b[i][j];
    }
    total += min(c1, c2);
  }
  cout << total << " " << nice << endl;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> VI;
typedef vector< vector<ll> > VVI;
typedef pair<ll, ll> PII;
typedef vector<ll> VPII;

#define REP(i, n) for(int i = 0; i < n; ++i)
#define RREP(i, n) for(int i = n - 1; i >= 0; --i)
#define FOR(i, x, y) for(int i = x; i <= y; ++i)
#define RFOR(i, x, y) for(int i = x; i >= y; --i)
#define SZ(a) (ll)(a).size()
#define ALL(a) (a).begin(),(a).end()
#define SORT(a) sort(ALL(a))
#define CLEAR(x) memset(x,0,sizeof x);
#define UNIQUE(c) SORT(c),(c).resize(unique(ALL(c))-(c).begin())
#define pb push_back
#define sqr(x) (x)*(x)
#define X first
#define Y second

const long double pi=acos(-1.0);
const long double eps = 1e-9;
const int INF = 1000000000;

int a[1024][1024];
int b[1024][1024];
int n, m;
int x, y;
int total, nice;

int main()
{
  cin >> n >> m;
  REP(i, n)
  {
    cin >> x >> y;
    ++a[x][y];
  }

  REP(i, m)
  {
    cin >> x >> y;
    ++b[x][y];
  }

  FOR(i, 1, 1000)
    FOR(j, 1, 1000)
    {
      int cur = min(a[i][j], b[i][j]);
      a[i][j] -= cur;
      b[i][j] -= cur;
      total += cur;
      nice += cur;
    }

  FOR(j, 1, 1000)
  {
    int c1 = 0;
    int c2 = 0;
    FOR(i, 1, 1000)
    {
      c1 += a[i][j];
      c2 += b[i][j];
    }
    total += min(c1, c2);
  }
  cout << total << " " << nice << endl;
}


#include <iostream>

using namespace std;

int n, m, buf;
int diam_flom[100000];
int diam_kolp[100000];
int hash1[1001000];
int hash2[1001000];
int zak = 0, kzak = 0;

void qsort1(int left, int right)
{
	int mid = diam_flom[left + (right - left) / 2];
	int i = left;
	int j = right;

	while(i <= j)
	{
		while (diam_flom[i] < mid) i++;
		while (diam_flom[j] > mid) j--;
	    if (i <= j)
	    {
			buf = diam_flom[i];
			diam_flom[i] = diam_flom[j];
			diam_flom[j] = buf;

			i++;
	        j--;
	    }
	}

	if (i < right) qsort1(i, right);
	if (j > left)  qsort1(left, j);
}

void qsort2(int left, int right)
{
	int mid = diam_kolp[left + (right - left) / 2];
	int i = left;
	int j = right;

	while(i <= j)
	{
		while (diam_kolp[i] < mid) i++;
		while (diam_kolp[j] > mid) j--;
	    if (i <= j)
	    {
			buf = diam_kolp[i];
			diam_kolp[i] = diam_kolp[j];
			diam_kolp[j] = buf;

			i++;
	        j--;
	    }
	}

	if (i < right) qsort2(i, right);
	if (j > left)  qsort2(left, j);
}

void main()
{
	cin >> n >> m;

	for (int i = 0; i< n; i++)
	{
		cin >> buf >> diam_flom[i];
		hash1[diam_flom[i] * 1000 + buf] ++;
	}

	for(int i = 0; i < m; i++)
	{
		cin >> buf >> diam_kolp[i];
		hash2[diam_kolp[i] * 1000 + buf] ++;
	}

	qsort1(0, n-1);
	qsort2(0, m-1);

	for (int i = 0, j = 0; ((i<n)&&(j<m)) ; i++)
	{
		while(diam_kolp[j] < diam_flom[i]) j++;
		if (diam_flom[i] == diam_kolp[j])
		{
			zak++;
			j++;
		}
	}

	for (int i = 0; i < 1001000; i++)
	{
		if (hash1[i] < hash2[i]) kzak += hash1[i];
		else
			kzak +=hash2[i];
	}

	cout << zak << ' ' << kzak;
}


#include <iostream>

using namespace std;

int n, m, buf;
int color_flom[100000], diam_flom[100000];
int diam_kolp[100000];
int a[1001][1001];
int zak = 0, kzak = 0;

void qsort1(int left, int right)
{
	int mid = diam_flom[left + (right - left) / 2];
	int i = left;
	int j = right;

	while(i <= j)
	{
		while (diam_flom[i] < mid) i++;
		while (diam_flom[j] > mid) j--;
	    if (i <= j)
	    {
			buf = diam_flom[i];
			diam_flom[i] = diam_flom[j];
			diam_flom[j] = buf;

			buf = color_flom[i];
			color_flom[i] = color_flom[j];
			color_flom[j] = buf;

			i++;
	        j--;
	    }
	}

	if (i < right) qsort1(i, right);
	if (j > left)  qsort1(left, j);
}

void qsort2(int left, int right)
{
	int mid = diam_kolp[left + (right - left) / 2];
	int i = left;
	int j = right;

	while(i <= j)
	{
		while (diam_kolp[i] < mid) i++;
		while (diam_kolp[j] > mid) j--;
	    if (i <= j)
	    {
			buf = diam_kolp[i];
			diam_kolp[i] = diam_kolp[j];
			diam_kolp[j] = buf;

			i++;
	        j--;
	    }
	}

	if (i < right) qsort2(i, right);
	if (j > left)  qsort2(left, j);
}

void main()
{
	cin >> n >> m;

	for (int i = 0; i< n; i++)
	{
		cin >> color_flom[i] >> diam_flom[i];
	}

	for(int i = 0; i < m; i++)
	{
		cin >> buf >> diam_kolp[i];
		a[diam_kolp[i]][buf]++;
	}

	qsort1(0, n-1);
	qsort2(0, m-1);

	for (int i = 0, j = 0; ((i<n)&&(j<m)) ; i++)
	{
		while(diam_kolp[j] < diam_flom[i]) j++;
		if (diam_flom[i] == diam_kolp[j])
		{
			zak++;
			if (a[diam_flom[i]][color_flom[i]] > 0)
			{
				a[diam_flom[i]][color_flom[i]] --;
				kzak ++;
			}
			j++;
		}
	}

	cout << zak << ' ' << kzak;
}


#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>

using namespace std;

#define pb push_back
#define mp make_pair

int a[1000][1000];
int b[1000][1000];

int main(){
	int n, m, c, d, u = 0, v = 0;
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	cin >> n >> m;
	for (int i=0; i<n; i++){
		cin >> c >> d;
		a[d][c]++;
	}
	for (int i=0; i<m; i++){
		cin >> c >> d;
		b[d][c]++;
	}
	for (d = 0; d < 1000; d++){
		int sumA = 0;
		int sumB = 0;
		int equals = 0;
		for (c = 0; c < 1000; c++){
			sumA += a[d][c];
			sumB += b[d][c];
			equals += min(a[d][c], b[d][c]);
		}
		u += min(sumA, sumB);
		v += equals;
	}
	cout << u << " " << v;
}


#include <algorithm>
#include <iostream>
#include <map>

using namespace std;

#define mp make_pair

int main(){
	int n, m, u = 0, v = 0;
	cin >> n >> m;
	map<pair<int,int>,int> a, b;
	map<int,int> c,d;
	for (int i=0; i<n; i++){
		int x, y;
		cin >> x >> y;
		a[mp(x,y)]++;
	}
	for (int i=0; i<m; i++){
		int x, y;
		cin >> x >> y;
		b[mp(x,y)]++;
	}
	for (map<pair<int,int>,int>::iterator i = b.begin(); i != b.end(); i++){
		pair<int,int> x = i->first;
		if (a.count(x) && a[x] != 0){
			u += min(a[x],b[x]);
			v += min(a[x],b[x]);
			a[x] > b[x] ? a[x] -= b[x], b[x] = 0 : b[x] -=a [x], a[x] = 0;
		}
		if (b[x] != 0) d[x.second] += b[x];
	}
	for (map<pair<int,int>,int>::iterator i = a.begin(); i != a.end(); i++){
		int x = (i->first).second;
		int y = i->second;
		if (y != 0){
			c[x] += y;
		}
	}
	for (map<int,int>::iterator i = d.begin(); i != d.end(); i++){
		int x = i->first;
		if (c.count(x))
			u += min(c[x],d[x]);
	}
	cout << u << " " << v;
}


#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>

using namespace std;

#define pb push_back
#define mp make_pair

int a[1001][1001];
int b[1001][1001];

int main(){
	int n, m, c, d, u = 0, v = 0;
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	cin >> n >> m;
	for (int i=0; i<n; i++){
		cin >> c >> d;
		a[d][c]++;
	}
	for (int i=0; i<m; i++){
		cin >> c >> d;
		b[d][c]++;
	}
	for (d = 0; d < 1001; d++){
		int sumA = 0;
		int sumB = 0;
		int equals = 0;
		for (c = 0; c < 1001; c++){
			sumA += a[d][c];
			sumB += b[d][c];
			equals += min(a[d][c], b[d][c]);
		}
		u += min(sumA, sumB);
		v += equals;
	}
	cout << u << " " << v;
}


#include <vector>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <list>
#include <bitset>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vint;
typedef vector<string> vstr;
typedef pair<int, int> pint;

#define TWO(k)  (1<<k)
#define TWOL(k) (((LL)(1)<<(k)))
#define MP make_pair
#define MIN(a,b) ( (a)<(b)?(a):(b) )
#define MAX(a,b) ( (a)>(b)?(a):(b) )
#define LS(x) 	 ((x)<<1)
#define RS(x) 	 (((x)<<1)+1)

const double PI = acos(-1.0);
const double EPS = 1e-9;
const int oo = 210000000;

typedef struct node{
    int x, y;
}node;

bool cmp1( node a, node b)
{
    if( a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

node data1[100010];
node data2[100010];

int main()
{
    //freopen("E:/in.txt","r",stdin);freopen("E:/out.txt","w",stdout);
    int n, m;
    while( scanf("%d%d", &n, &m) == 2)
    {
        for( int i = 0; i < n; i++) scanf("%d%d", &data1[i].y, &data1[i].x);
        for( int i = 0; i < m; i++) scanf("%d%d", &data2[i].y, &data2[i].x);
        sort( data1, data1 + n, cmp1);
        sort( data2, data2 + m, cmp1);
        int h1 = 0, t1 = 0;
        int h2 = 0, t2 = 0;
        int ans1 = 0, ans2 = 0;
        int k = 0;
        while( t1 < n && t2 < m && k < m)
        {
            while( data1[h1].x == data1[t1].x && h1 < n) h1++;
            if( data1[h1].x != data1[t1].x) h1 --;
            //cout<<"t1 h1 k"<<t1<<' '<<h1<<' '<<k<<endl;
            for( k = t2; k < m; k++)
            {
                if( data2[k].x >= data1[t1].x)
                    break;
            }
            if( k >= m) break;
            t2 = h2 = k; //cout<<"t1 h1 k"<<t1<<' '<<h1<<' '<<k<<endl;
            if(data2[k].x == data1[t1].x)
            {
                while( data2[h2].x == data1[t1].x && h2 < m) h2++;
                if( data2[h2].x != data1[t1].x) h2 --;
                ans1 += min( h1 - t1 + 1, h2 - t2 + 1);
                for( int i = t1, j = t2; i <= h1 && j <= h2; i++, j++)
                {
                    if( data1[i].y == data2[j].y) ans2 ++;
                }
                h2++; t2 = h2;
            }
            else
            {
                h2 = t2 = k;
            }
            h1++; t1 = h1;
        }
        printf("%d %d\n", ans1, ans2);
    }
    return(0);
}


#include <vector>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <list>
#include <bitset>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vint;
typedef vector<string> vstr;
typedef pair<int, int> pint;

#define TWO(k)  (1<<k)
#define TWOL(k) (((LL)(1)<<(k)))
#define MP make_pair
#define MIN(a,b) ( (a)<(b)?(a):(b) )
#define MAX(a,b) ( (a)>(b)?(a):(b) )
#define LS(x) 	 ((x)<<1)
#define RS(x) 	 (((x)<<1)+1)

const double PI = acos(-1.0);
const double EPS = 1e-9;
const int oo = 210000000;

typedef struct node{
    int x, y;
}node;

inline bool cmp1( node a, node b)
{
    if( a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

node data1[100010];
node data2[100010];

int main()
{
    //freopen("E:/in.txt","r",stdin);freopen("E:/out.txt","w",stdout);
    int n, m;
    while( scanf("%d%d", &n, &m) == 2)
    {
        for( int i = 0; i < n; i++) scanf("%d%d", &data1[i].y, &data1[i].x);
        for( int i = 0; i < m; i++) scanf("%d%d", &data2[i].y, &data2[i].x);
        sort( data1, data1 + n, cmp1);
        sort( data2, data2 + m, cmp1);
        int h1 = 0, t1 = 0;
        int h2 = 0, t2 = 0;
        int ans1 = 0, ans2 = 0;
        int k = 0;
        int flag1[1010];
        int flag2[1010];
        while( t1 < n && t2 < m)
        {
            while( data1[h1].x == data1[t1].x && h1 < n) h1++;
            if( h1 == n || data1[h1].x != data1[t1].x) h1 --;
            for( k = t2; k < m; k++)
            {
                if( data2[k].x >= data1[t1].x)
                    break;
            }
            if( k >= m) break;
            t2 = h2 = k;
            if(data2[k].x == data1[t1].x)
            {
                while( data2[h2].x == data1[t1].x && h2 < m) h2++;
                if( h2 == m || data2[h2].x != data1[t1].x) h2 --;
                //cout<<"t1 h1 t2 h2"<<t1<<' '<<h1<<' '<<t2<<' '<<h2<<endl;
                ans1 += min( h1 - t1 + 1, h2 - t2 + 1);
                memset( flag1, 0, sizeof( flag1));
                memset( flag2, 0, sizeof( flag2));
                for( int i = t1; i <= h1; i++) flag1[data1[i].y]++;
                for( int i = t2; i <= h2; i++) flag2[data2[i].y]++;
                for( int i = 0; i <= 1000; i++) ans2 += min( flag1[i], flag2[i]);
                h2++; t2 = h2;
            }
            h1++; t1 = h1;
        }
        printf("%d %d\n", ans1, ans2);
    }
    return(0);
}


#include <vector>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <list>
#include <bitset>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vint;
typedef vector<string> vstr;
typedef pair<int, int> pint;

#define TWO(k)  (1<<k)
#define TWOL(k) (((LL)(1)<<(k)))
#define MP make_pair
#define MIN(a,b) ( (a)<(b)?(a):(b) )
#define MAX(a,b) ( (a)>(b)?(a):(b) )
#define LS(x) 	 ((x)<<1)
#define RS(x) 	 (((x)<<1)+1)

const double PI = acos(-1.0);
const double EPS = 1e-9;
const int oo = 210000000;

typedef struct node{
    int x, y;
}node;

inline bool cmp1( node a, node b)
{
    if( a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

node data1[100010];
node data2[100010];

int main()
{
    //freopen("E:/in.txt","r",stdin);freopen("E:/out.txt","w",stdout);
    int n, m;
    while( scanf("%d%d", &n, &m) == 2)
    {
        for( int i = 0; i < n; i++) scanf("%d%d", &data1[i].y, &data1[i].x);
        for( int i = 0; i < m; i++) scanf("%d%d", &data2[i].y, &data2[i].x);
        sort( data1, data1 + n, cmp1);
        sort( data2, data2 + m, cmp1);
        int h1 = 0, t1 = 0;
        int h2 = 0, t2 = 0;
        int ans1 = 0, ans2 = 0;
        int k = 0;
        while( t1 < n && t2 < m)
        {
            while( data1[h1].x == data1[t1].x && h1 < n) h1++;
            if( h1 == n || data1[h1].x != data1[t1].x) h1 --;
            for( k = t2; k < m; k++)
            {
                if( data2[k].x >= data1[t1].x)
                    break;
            }
            if( k >= m) break;
            t2 = h2 = k;
            if(data2[k].x == data1[t1].x)
            {
                while( data2[h2].x == data1[t1].x && h2 < m) h2++;
                if( h2 == m || data2[h2].x != data1[t1].x) h2 --;
                //cout<<"t1 h1 t2 h2"<<t1<<' '<<h1<<' '<<t2<<' '<<h2<<endl;
                ans1 += min( h1 - t1 + 1, h2 - t2 + 1);
                for( int i = t1, j = t2; i <= h1 && j <= h2; i++, j++)
                {
                    if( data1[i].y == data2[j].y) ans2 ++;
                }
                h2++; t2 = h2;
            }
            h1++; t1 = h1;
        }
        printf("%d %d\n", ans1, ans2);
    }
    return(0);
}


#include <vector>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <list>
#include <bitset>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vint;
typedef vector<string> vstr;
typedef pair<int, int> pint;

#define TWO(k)  (1<<k)
#define TWOL(k) (((LL)(1)<<(k)))
#define MP make_pair
#define MIN(a,b) ( (a)<(b)?(a):(b) )
#define MAX(a,b) ( (a)>(b)?(a):(b) )
#define LS(x) 	 ((x)<<1)
#define RS(x) 	 (((x)<<1)+1)

const double PI = acos(-1.0);
const double EPS = 1e-9;
const int oo = 210000000;

typedef struct node{
    int x, y;
}node;

bool cmp1( node a, node b)
{
    if( a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

node data1[100010];
node data2[100010];

int main()
{
    //freopen("E:/in.txt","r",stdin);freopen("E:/out.txt","w",stdout);
    int n, m;
    while( scanf("%d%d", &n, &m) == 2)
    {
        for( int i = 0; i < n; i++) scanf("%d%d", &data1[i].y, &data1[i].x);
        for( int i = 0; i < m; i++) scanf("%d%d", &data2[i].y, &data2[i].x);
        sort( data1, data1 + n, cmp1);
        sort( data2, data2 + m, cmp1);
        int h1 = 0, t1 = 0;
        int h2 = 0, t2 = 0;
        int ans1 = 0, ans2 = 0;
        int k = 0;
        while( t1 < n && t2 < m && k < m)
        {
            while( data1[h1].x == data1[t1].x && h1 < n) h1++;
            if( data1[h1].x != data1[t1].x) h1 --;
            //cout<<"t1 h1 k"<<t1<<' '<<h1<<' '<<k<<endl;
            for( k = t2; k < m; k++)
            {
                if( data2[k].x >= data1[t1].x)
                    break;
            }
            if( k >= m) break;
            t2 = h2 = k; //cout<<"t1 h1 k"<<t1<<' '<<h1<<' '<<k<<endl;
            if(data2[k].x == data1[t1].x)
            {
                while( data2[h2].x == data1[t1].x && h2 < m) h2++;
                if( data2[h2].x != data1[t1].x) h2 --;
                ans1 += min( h1 - t1 + 1, h2 - t2 + 1);
                for( int i = t1, j = t2; i <= h1 && j <= h2; i++, j++)
                {
                    if( data1[i].y == data2[j].y) ans2 ++;
                }
            }
            h1++; t1 = h1;
            h2++; t2 = h2;
        }
        printf("%d %d\n", ans1, ans2);
    }
    return(0);
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <algorithm>
#include <cmath>
using namespace std;

#pragma comment(linker, "/STACK:100000000")

int matrix[1001][1001] = {0};
int d[1001] = {0};

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        d[y]++;
        matrix[x][y]++;
    }
    int all = 0, good = 0;
    for(int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        if(matrix[a][b] > 0) {
            all++;
            good++;
            matrix[a][b]--;
            d[b]--;
        }
        else if(d[b] > 0) {
            all++;
            d[b]--;
        }
    }
    printf("%d %d\n", all, good);
    return 0;
}

    //freopen("windows.in", "rt", stdin);
    //freopen("windows.out", "wt", stdout);


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <algorithm>
#include <cmath>
using namespace std;

#pragma comment(linker, "/STACK:100000000")

int matrix[1001][1001] = {0};
int d[1001] = {0};

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        d[y]++;
        matrix[x][y]++;
    }
    int all = 0, good = 0;
    for(int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        if(matrix[a][b] > 0) {
            if(d[b] > 0) {
                all++;
                d[b]--;
            }
            good++;
            matrix[a][b]--;
        }
        else if(d[b] > 0) {
            all++;
            d[b]--;
        }
    }
    printf("%d %d\n", all, good);
    return 0;
}

    //freopen("windows.in", "rt", stdin);
    //freopen("windows.out", "wt", stdout);


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <algorithm>
#include <cmath>
using namespace std;

#pragma comment(linker, "/STACK:100000000")

int matrix[1001][1001] = {0};
int d[1001] = {0};

int main() {
    for(int i = 0; i < 1001; i++) {
        for(int j = 0; j < 1001; j++) {
            matrix[i][j] = 0;
        }
        d[i] = 0;
    }
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        d[y]++;
        matrix[x][y]++;
    }
    int all = 0, good = 0;
    for(int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        if(matrix[a][b] > 0) {
            all++;
            good++;
            matrix[a][b]--;
            d[b]--;
        }
        else if(d[b] > 0) {
            all++;
            d[b]--;
        }
    }
    printf("%d %d\n", all, good);
    return 0;
}

    //freopen("windows.in", "rt", stdin);
    //freopen("windows.out", "wt", stdout);


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <algorithm>
#include <cmath>
using namespace std;

#pragma comment(linker, "/STACK:100000000")

int matrix[1001][1001] = {0};
int d[1001] = {0};
queue<int> q;

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        d[y]++;
        matrix[x][y]++;
    }
    int all = 0, good = 0;
    for(int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        if(matrix[a][b] > 0) {
            all++;
            good++;
            matrix[a][b]--;
            d[b]--;
        }
        else if(d[b] > 0) {
            q.push(b);
        }
    }
    for(int i = 0, maxi = q.size(); i < maxi; i++) {
        int b = q.front();
        q.pop();
        if(d[b] > 0) {
            d[b]--;
            all++;
        }
    }
    printf("%d %d\n", all, good);
    return 0;
}

    //freopen("windows.in", "rt", stdin);
    //freopen("windows.out", "wt", stdout);


#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int n,m;
    cin >> n >> m;

    vector<pair<int,int>> markers(n);
    vector<pair<int,int>> caps(m);

    int color,diam;
    for (int i = 0; i < n; i++) {
        cin >> color >> diam;
        markers[i] = make_pair(diam,color);
    }
    for (int i = 0; i < m; i++) {
        cin >> color >> diam;
        caps[i] = make_pair(diam,color);
    }

    sort(markers.begin(), markers.end());
    sort(caps.begin(), caps.end());

    int unmatched_markers = 0, unmatched_caps = 0;
    int beautiful = 0, unbeautiful = 0;

    int old_marker_diam = 0, old_cap_diam = 0;
    int marker_diam, cap_diam;
    int marker_color, cap_color;

    int i = 0, j = 0;
    while (i < n && j < m) {
        marker_diam = markers[i].first;
        cap_diam = caps[j].first;

        if (marker_diam != old_marker_diam || cap_diam != old_cap_diam && marker_diam == cap_diam)
            unbeautiful += min(unmatched_markers, unmatched_caps);

        if (marker_diam == cap_diam) {
            marker_color = markers[i].second;
            cap_color = caps[j].second;

            if (marker_color == cap_color) {
                beautiful += 1;
                i++;
                j++;
            }
            else if (marker_color < cap_color) {
                i++;
                unmatched_markers++;
            }
            else if (marker_color > cap_color) {
                j++;
                unmatched_caps++;
            }
        }
        else if (marker_diam < cap_diam) {
            i++;
            unmatched_markers++;
        }
        else if (marker_diam > cap_diam) {
            j++;
            unmatched_caps++;
        }

        old_marker_diam = marker_diam;
        old_cap_diam = cap_diam;
    }

    unbeautiful += min(unmatched_markers, unmatched_caps);

    cout << (beautiful + unbeautiful) << " " << beautiful << endl;

    return 0;
}


#include <algorithm>
#include <iostream>
#include <map>

using namespace std;

int main()
{
    int n,m;
    cin >> n >> m;

    map<pair<int,int>,int> color_and_diam;
    map<int,int> marker_diams;
    map<int,int> cap_diams;
    int beautiful = 0;
    int unbeautiful = 0;

    int color,diam;
    for (int i = 0; i < n; i++) {
        cin >> color >> diam;
        color_and_diam[make_pair(color,diam)] += 1;
        marker_diams[diam] += 1;
    }
    for (int i = 0; i < m; i++) {
        cin >> color >> diam;
        pair<int,int> cap = make_pair(color,diam);
        if (color_and_diam[cap] > 0) {
            beautiful += 1;
            color_and_diam[cap] -= 1;
            marker_diams[diam] -= 1;
        }
        else
            cap_diams[diam] += 1;
    }

    for (map<int,int>::iterator iter = marker_diams.begin(); iter != marker_diams.end(); ++iter)
        if (cap_diams[iter->first] > 0 && marker_diams[iter->first] > 0)
            unbeautiful += min(marker_diams[iter->first], cap_diams[iter->first]);

    cout << (beautiful + unbeautiful) << " " << beautiful << endl;
    return 0;
}


#include <iostream>
#include <algorithm>

int main()
{
    int n, m;
    std::cin >> n >> m;
    std::pair<int, int> *maker = new std::pair<int, int>[n];
    std::pair<int, int> *cap = new std::pair<int, int>[m];

    for (int i = 0; i != n; ++i){std::cin >>  maker[i].second >> maker[i].first;}
    for (int i = 0; i != m; ++i){std::cin >> cap[i].second >> cap[i].first;}

    std::sort(maker, maker + n);
    std::sort(cap, cap + m);

    int ii = 0, j = 0, btfcls = 0, cls = 0;
    while (ii < n && j < m)
    {
        if (maker[ii] == cap[j])
        {
            ++ii, ++j, ++btfcls;
            continue;
        }
        maker[ii] < cap[j] ? ++ii : ++j;
    }
    ii = 0;
    j = 0;
    while (ii < n && j < m)
    {
        if (maker[ii].first == cap[j].first) {++ii, ++j, ++cls; continue;}
        maker[ii].first < cap[j].first ? ++ii : ++j;
    }
    std::cout << cls << " " << btfcls << std::endl;
    return 0;
}


#include <iostream>

int main()
{
    int n, m;
    std::cin >> n >> m;
    std::pair<int, int> *maker = new std::pair<int, int>[n];
    std::pair<int, int> *cap = new std::pair<int, int>[m];

    for (int i = 0; i != n; ++i)
    {
        std::cin >> maker[i].first >> maker[i].second;
    }
    for (int i = 0; i != m; ++i)
    {
        std::cin >> cap[i].first >> cap[i].second;
    }

    int btfcls = 0, cls = 0;
    for (int i = 0; i != n; ++i)
    {
        for (int j = 0; j != m; ++j)
        {
            if (cap[j] == maker[i]) {++btfcls; break;}
        }
    }
    for (int i = 0; i != n; ++i)
    {
        for (int j = 0; j != m; ++j)
        {
            if (cap[j].second == maker[i].second) {++cls; maker[i].second = 0; break;}
        }
    }
    std::cout << cls << " " << btfcls;
    return 0;
}


#include <iostream>
#include <utility>
#include <algorithm>
using namespace std;

pair<int,int> fl[100010];
pair<int,int> kol[100010];
int colFl[100010];
int colKol[100010];

int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        pair<int,int> a;
        cin>>a.second>>a.first;
        fl[i]=a;
    }
    sort(fl,fl+n);
    for(int i=0;i<m;i++){
        pair<int,int> a;
        cin>>a.second>>a.first;
        kol[i]=a;
    }
    sort(kol,kol+m);int start=0;
    int i=0;
    while(i<n){
        int k=0;
        int l=0;
        colFl[k]=fl[i].second;k++;
        int j=i+1;
        while (fl[i].first==fl[j].first&&j<n){
            colFl[k]=fl[j].second;
            k++;j++;
        }
        j=start;
        while (fl[i].first>kol[j].first&&j<m){j++;}
        while (fl[i].first==kol[j].first&&j<m){
            colKol[l]=kol[j].second;
            l++;j++;
        }
        start=j;
        int first=0;
        for(int p=0;p<k;p++){
            int pp=first;
            if (first==l) break;
            while (colFl[p]>colKol[pp]){pp++;}
            while (colFl[p]<=colKol[pp]&&pp<l){
            if (colFl[p]==colKol[pp]){u++;first=pp+1;break;}
            else{pp++; first=pp;}
            }
        }
        if (k<=l) v+=k;
        else v+=l;
    i+=k;
    if (start==m) break;
    }
    cout<<v<<" "<<u;
    return 0;
}


#include <iostream>
using namespace std;

int fl[1010][1010];
int Kol[1010];
int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        int a,b;
        cin>>a>>b;
        fl[a][b]++;
        Kol[b]++;
    }
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        if (fl[a][b]!=0){fl[a][b]--;Kol[b]--;u++;if (Kol[b]>=0){v++;}}
        else{if (Kol[b]>0) {Kol[b]--;v++;}}
    }
    cout<<v<<" "<<u;
    return 0;
}


#include <iostream>
using namespace std;

int fl[1000][1000];
int Kol[1000];
int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        int a,b;
        cin>>a>>b;
        fl[a][b]++;
        Kol[b]++;
    }
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        if (fl[a][b]!=0){fl[a][b]--;u++;v++;}
        else{
            if (Kol[b]>0) {Kol[b]--;v++;}
        }
    }
    cout<<v<<" "<<u;
    return 0;
}


#include <iostream>
#include <utility>
#include <algorithm>
using namespace std;

pair<int,int> fl[100010];
pair<int,int> kol[100010];
int colFl[100010];
int colKol[100010];

int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        pair<int,int> a;
        cin>>a.second>>a.first;
        fl[i]=a;
    }
    sort(fl,fl+n);
    for(int i=0;i<m;i++){
        pair<int,int> a;
        cin>>a.second>>a.first;
        kol[i]=a;
    }
    sort(kol,kol+m);int start=0;
    for(int i=0;i<n;i++){
        int k=0;
        int l=0;
        colFl[k]=fl[i].second;k++;
        int j=i+1;
        while (fl[i].first==fl[j].first&&j<n){
            colFl[k]=fl[j].second;
            k++;j++;
        }
        j=start;
        while (fl[i].first>kol[j].first&&j<m){j++;}
        while (fl[i].first==kol[j].first&&j<m){
            colKol[l]=kol[j].second;
            l++;j++;
        }
        start=j;int first=0;
        for(int p=0;p<k;p++){
            int pp=first;
            while (colFl[p]<colKol[pp]){pp++;}
            if (colFl[p]==colKol[pp]){u++;first=pp+1;}
            else{first=pp;}
        }
        if (k<=l) v+=k;
        else v+=l;

    }
    cout<<v<<" "<<u;
    return 0;
}


#include <iostream>
using namespace std;

int fl[1000][1000];
int Kol[1000];
int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        int a,b;
        cin>>a>>b;
        fl[a][b]++;
        Kol[b]++;
    }
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        if (fl[a][b]!=0){fl[a][b]--;Kol[b]--;u++;v++;}
        else{
            if (Kol[b]>0) {Kol[b]--;v++;}
        }
    }
    cout<<v<<" "<<u;
    return 0;
}


#include <iostream>
#include <utility>
#include <vector>
using namespace std;

pair<int,int> fl[100010];
pair<int,int> kol[100010];
int colFl[100010];
int colKol[100010];

int main(){
    int v=0,u=0;
    int n, m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        pair<int,int> a;
        cin>>a.first>>a.second;
        fl[i]=a;
    }
    for(int i=0;i<m;i++){
        pair<int,int> a;
        cin>>a.first>>a.second;
        kol[i]=a;
    }

    for(int i=0;i<n;i++){
        int k=0;
        int l=0;
        if(fl[i].second!=0){
            colFl[k]=fl[i].first;k++;
        for(int j=i+1;j<n;j++){
            if (fl[i].second==fl[j].second){
                colFl[k]=fl[j].first;
                fl[j].second=0;
                k++;
            }
        }
        for(int j=0;j<m;j++){
            if (fl[i].second==kol[j].second){
                colKol[l]=kol[j].first;
                l++;
            }
        }
        for(int p=0;p<k;p++){
            for(int pp=0;pp<l;pp++){
                if (colFl[p]==colKol[pp]){colKol[pp]=0;u++;break;}
            }
        }
        if (k<=l) v+=k;
        else v+=l;
        }
    }
    cout<<v<<" "<<u;
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<queue>
#include<ctime>
#include <complex>
#include <deque>
using namespace std;

bool cmp(int a,int b){
	if(a>b)
		return true;
	else return false;
}
#define sortS(a) sort(a.begin(),a.end())
#define sortN(a) sort(a.begin(),a.end(),cmp)
const int MAX=1000;
vector<int> all[MAX+2];
vector<int> all2[MAX+2];
bool fun(int a , int V) {
	int L = 0;
	int R = all[a].size()-1;
    while (L <= R) {
        int M = (L + R) / 2;
		if (all[a][M] == V){
			all[a].erase(all[a].begin()+M);
            return true;
		}
        else if (all[a][M] > V)
              R = M - 1;
        else
              L = M + 1;
      }
      return false;
}
int main(){
	//freopen("in.txt", "r", stdin );
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n+m;i++){
		int x,y;
		cin>>x>>y;
		if( i<n )
			all[y].push_back(x);
		else
			all2[y].push_back(x);
	}
	for(int i=0;i<MAX+2;i++){
		sortS(all[i]);
		sortS(all2[i]);
	}
	int cls=0,beaut=0;
	for(int i=0;i<MAX+2;i++){
		for(int j=0;j<all2[i].size();j++){
			if ( fun(i,all2[i][j]) ){
				beaut++;
				all2[i].erase(all2[i].begin()+j);
				j--;
			}
		}

		cls += min (all[i].size(),all2[i].size()) ;
	}
	cout<<cls+beaut<< " " <<beaut<<endl;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<queue>
#include<ctime>
#include <complex>
#include <deque>
using namespace std;

bool cmp(int a,int b){
	if(a>b)
		return true;
	else return false;
}

#define sortS(a) sort(a.begin(),a.end())
#define sortN(a) sort(a.begin(),a.end(),cmp)

int n, m, data[1010][1010], vis[1010], close, beaut;
void add(int s, int c, int t){
    if( t*vis[s] < 0 )
		close++;
    if( t*data[s][c] < 0)
		beaut++;
    vis[s]+=t;
    data[s][c]+=t;
}
int main(){
	//freopen("in.txt","r",stdin);
    cin>>n>>m;
    for(int i=0; i<n+m ;i++){
        int s,c;
        cin>>c>>s;
        if(i<n)
			add(s, c, 1);
        else
			add(s, c, -1);
    }
	cout<<close<< " "<<beaut<<endl;
}


#include <iostream>
using namespace std;

void main()
{
	int n,m,f;
	cin >> n >> m;
	int *x=new int [n];
	int *y=new int [n];
	int *a=new int [m];
	int *b=new int [m];
	bool *q1=new bool [n];
	bool *q2=new bool [m];
	for(f=0;f<n;f++)
	{
		cin >> x[f] >> y[f];
		q1[f]=false;
	}
	for(f=0;f<m;f++)
	{
		cin >> a[f] >> b[f];
		q2[f]=false;
	}
	int u=0,v=0,f1;
	for(f=0;f<n;f++)
	{
		for(f1=0;f1<m;f1++)
		{
			if(q2[f1]) continue;
			if((x[f]==a[f1])&&(y[f]==b[f1]))
			{
				q1[f]=true; q2[f1]=true;
				u++;++v;
				break;
			}
		}
	}
	for(f=0;f<n;f++)
	{
		if(q1[f]) continue;
		for(f1=0;f1<m;f1++)
		{
			if(q2[f1]) continue;
			if(y[f]==b[f1])
			{
				q2[f1]=true;
				++u;
				break;
			}
		}
	}
	cout<<u<<' '<<v;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	int fail[100005];
	int c = 0;
	k     = 0;
	p     = 0;
	int* cash = new int[1000010];
	ZeroMemory(cash,sizeof(int)*1000010);

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[(y-1)*1000 + x - 1]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[(b-1)*1000 + a - 1] > 0)
		{
			k++;
			p++;
			cash[(b-1)*1000 + a - 1]--;
		}
		else fail[c++] = b;
	}

	for(int i = 0;i < c;i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[(fail[i]-1)*1000 + j] > 0)
			{
				k++;
				cash[(fail[i]-1)*1000 + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	int fail[100005];
	int c = 0;
	k     = 0;
	p     = 0;
	int* cash = new int[10000005];
	ZeroMemory(cash,sizeof(int)*10000005);

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[y*1000 + x]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[b*1000 + a] > 0)
		{
			k++;
			p++;
			cash[b*1000 + a]--;
		}
		else fail[c++] = b;
	}

	for(int i = 0;i < c;i++)
	{
		for(int j = 0;j < 1001;j++)
		{
			if(cash[fail[i]*1000 + j] > 0)
			{
				k++;
				cash[fail[i] + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	int fail[100005];
	int c = 0;
	k     = 0;
	p     = 0;
	int* cash = new int[10000005];
	ZeroMemory(cash,sizeof(int)*10000005);

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[y*1000 + x]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[b*1000 + a] > 0)
		{
			k++;
			p++;
			cash[b*1000 + a]--;
		}
		else fail[c++] = b;
	}

	for(int i = 0;i < c;i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[fail[i]*1000 + j] > 0)
			{
				k++;
				cash[fail[i] + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	int fail[100005];
	int c = 0;
	k     = 0;
	p     = 0;
	int* cash = new int[1000010];
	ZeroMemory(cash,sizeof(int)*1000010);

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[(y-1)*1000 + x]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[(b-1)*1000 + a] > 0)
		{
			k++;
			p++;
			cash[(b-1)*1000 + a]--;
		}
		else fail[c++] = b;
	}

	for(int i = 0;i < c;i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[(fail[i]-1)*1000 + j + 1] > 0)
			{
				k++;
				cash[fail[i] + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	k = 0;
	p = 0;
	bool cash[1000005];
	ZeroMemory(cash,sizeof(cash));
	deque<int> Fail;

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[y*1000 + x] = true;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[b*1000 + a])
		{
			k++;
			p++;
			cash[b*1000 + a] = false;
		}
		else Fail.push_back(b);
	}

	for(int i = 0;i < Fail.size();i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[Fail[i]*1000 + j])
			{
				k++;
				cash[Fail[i] + j] = false;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	int fail[100005];
	int c = 0;
	k     = 0;
	p     = 0;
	int* cash = new int[1000005];
	ZeroMemory(cash,sizeof(int)*1000005);

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[y*1000 + x]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[b*1000 + a] > 0)
		{
			k++;
			p++;
			cash[b*1000 + a]--;
		}
		else fail[c++] = b;
	}

	for(int i = 0;i < c;i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[fail[i]*1000 + j] > 0)
			{
				k++;
				cash[fail[i] + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include <iostream>
#include <math.h>
#include <Windows.h>
#include <deque>

using namespace std;

int main()
{
	int n,m;
	int k,p;
	k = 0;
	p = 0;
	int* cash = new int[1000005];
	ZeroMemory(cash,sizeof(int)*1000005);
	deque<int> Fail;

	cin >> n >> m;

	for(int i = 0;i < n;i++)
	{
		int x,y;
		cin >> x >> y;

		cash[y*1000 + x]++;
	}
	for(int i = 0;i < m;i++)
	{
		int a,b;
		cin >> a >> b;

		if(cash[b*1000 + a] > 0)
		{
			k++;
			p++;
			cash[b*1000 + a]--;
		}
		else Fail.push_back(b);
	}

	for(int i = 0;i < Fail.size();i++)
	{
		for(int j = 0;j < 1000;j++)
		{
			if(cash[Fail[i]*1000 + j] > 0)
			{
				k++;
				cash[Fail[i] + j]--;
				break;
			}
		}
	}

	cout << k << " " <<  p << endl;

	return 0;
}


#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
	int x;
	int y;
}p;
int cmp(p x,p y)
{
	return x.y<y.y;
}
int cmq(p x,p y)
{
	if(x.x==y.x)
		return x.y<y.y;
	else
		return x.x<y.x;
}
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		p a[100001];
		p b[100001];
		for(int i=0;i<n;++i)
			cin>>a[i].x>>a[i].y;
		for(int i=0;i<m;++i)
			cin>>b[i].x>>b[i].y;
		sort(a,a+n,cmp);
		sort(b,b+m,cmp);
		int l1=0;
		int l2=0;
		int sum1=0;
		while(l1<n&&l2<m)
		{
			if(a[l1].y>b[l2].y)
				l2++;
			else if(a[l1].y==b[l2].y)
			{
				l1++;
				l2++;
				sum1++;
			}
			else
				l1++;
		}
		l1=0;
		l2=0;
		sort(a,a+n,cmq);
		sort(b,b+m,cmq);
		int sum2=0;
		while(l1<n&&l2<m)
		{
			if(a[l1].x>b[l2].x)
				l2++;
			else if(a[l1].x==b[l2].x)
			{
				if(a[l1].y>b[l2].y)
					l2++;
				else if(a[l1].y==b[l2].y)
				{
					l1++;
					l2++;
					sum2++;
				}
				else
					l1++;
			}
			else
				l1++;
		}
		cout<<sum1<<" "<<sum2<<endl;
	}
	return 0;
}


#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node
{
	int x;
	int y;
}p;
int cmp(p x,p y)
{
	return x.y<y.y;
}
int cmq(p x,p y)
{
	return x.x<y.x;
}
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		p a[100001];
		p b[100001];
		for(int i=0;i<n;++i)
			cin>>a[i].x>>a[i].y;
		for(int i=0;i<m;++i)
			cin>>b[i].x>>b[i].y;
		sort(a,a+n,cmp);
		sort(b,b+m,cmp);
		int l1=0;
		int l2=0;
		int sum1=0;
		while(l1<n&&l2<m)
		{
			if(a[l1].y>b[l2].y)
				l2++;
			else if(a[l1].y==b[l2].y)
			{
				l1++;
				l2++;
				sum1++;
			}
			else
				l1++;
		}
		l1=l2=0;
		sort(a,a+m,cmq);
		sort(b,b+m,cmq);
		int sum2=0;
		while(l1<n&&l2<m)
		{
			if(a[l1].x>b[l2].x)
				l2++;
			else if(a[l1].x==b[l2].x)
			{
				if(a[l1].y>b[l2].y)
					l2++;
				else if(a[l1].y==b[l2].y)
				{
					l1++;
					l2++;
					sum2++;
				}
				else
					l1++;
			}
			else
				l1++;
		}
		cout<<sum1<<" "<<sum2<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <conio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
using namespace std;
int m, n;
struct node
{
	int c, d;
};
vector<node> t, t2;
bool option(const node& a, const node& b)
{
	if (a.d < b.d)
		return true;
	else
		if (a.d == b.d && a.c < b.c)
			return true;
	return false;
}
void main()
{
	scanf_s("%d%d", &n, &m);
	t.resize(n);

	for (int i = 0; i < n; i++)
	{
		scanf_s("%d%d", &t[i].c, &t[i].d);
	}
	t2.resize(m);
	for (int i = 0; i < m; i++)
	{
		scanf_s("%d%d", &t2[i].c, &t2[i].d);
	}
	sort(t.begin(), t.end(), option);
	sort(t2.begin(), t2.end(), option);
	int kq=0, j=0, kq2=0;
	for (int i = 0; i < n; i++)
	{
		while (j < m && t2[j].d < t[i].d)
		{
			j++;
		}

		if (j < m)
			if (t2[j].d == t[i].d)
			{
				while (j<m && t2[j].d==t[i].d && t2[j].c<t[i].c)
				{
					j++;
				}
				if (j < m)

				{
					if (t2[j].d == t[i].d)

					{
						if (t2[j].c == t[i].c)

						{
							j++;
							kq2++;
						}

					}

				}
			}

	}

	j = 0;
	for (int i = 0; i < n; i++)
	{
		while (j < m && t2[j].d < t[i].d)
			j++;
		if (j == m)
			break;
		else
			if (t2[j].d == t[i].d)
			{
				j++;
				kq++;

			}

	}

	printf("%d %d", kq, kq2);

	//_getch();
}


#include <stdio.h>
#include <conio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
using namespace std;
int m, n;
struct node
{
	int c, d;
};
vector<node> v, v2, t, t2;
bool option(const node& a, const node& b)
{
	if (a.d < b.d)
		return true;
	else
		if (a.d == b.d && a.c < b.c)
			return true;
	return false;
}
void main()
{
	scanf_s("%d%d", &n, &m);
	t.resize(n);

	for (int i = 0; i < n; i++)
	{
		scanf_s("%d%d", &t[i].c, &t[i].d);
	}
	t2.resize(m);
	for (int i = 0; i < m; i++)
	{
		scanf_s("%d%d", &t2[i].c, &t2[i].d);
	}
	sort(t.begin(), t.end(), option);
	sort(t2.begin(), t2.end(), option);
	int kq = 0, j=0, kq2=0;
	for (int i = 0; i < n; i++)
	{
		while (j < m && t2[j].d < t[i].d)
		{
			v2.resize(v2.size() + 1);
			v2[v2.size() - 1] = t2[j];
			j++;

		}
		if (j == m)
		{
			v.resize(v.size() + 1);
			v[v.size() - 1] = t[i];
		}
		else
			if (t2[j].d == t[i].d)
			{
				while (j<m && t2[j].d==t[i].d && t2[j].c<t[i].c)
				{
					v2.resize(v2.size() + 1);
					v2[v2.size() - 1] = t2[j];
					j++;

				}
				if (j == m)
				{
					v.resize(v.size() + 1);
					v[v.size() - 1] = t[i];
				}
				else
				{
					if (t2[j].d > t[i].d)
					{
						v.resize(v.size() + 1);
						v[v.size() - 1] = t[i];
					}
					else
					{
						if (t2[j].c > t[i].c)
						{
							v.resize(v.size() + 1);
							v[v.size() - 1] = t[i];
						}
						else
						{
							j++;
							kq++;
							kq2++;
						}

					}

				}
			}

	}
	if (j <= m - 1)
	{
		for (int i = j; i < m; i++)
		{
			v2.resize(v2.size() + 1);
			v2[v2.size() - 1] = t2[i];
		}
	}
	j = 0;
	for (int i = 0; i < v.size(); i++)
	{
		while (j < v2.size() && v2[j].d < v[i].d)
			j++;
		if (j == v2.size())
			break;
		else
			if (v2[j].d == v[i].d)
			{
				j++;
				kq++;
			}
	}
	printf("%d %d", kq, kq2);

	/*int j = 0, i=0, t=-1, kq=0, kq2=0;
	while (i < n && j < m)
	{
		while (j < m && v2[j].d < v[i].d)
			j++;
		if (j == m)
			break;
		else
			if (v2[j].d == v[i].d)
			{
				if (t==-1)
					t = j;
				while (t < m && v2[t].d == v[i].d && v2[t].c < v[i].c)
					t++;
				if (t == m)
				{
					i++;
					j++;
					kq++;
				}
				else
				{

				}

			}

	}
	*/

	//();
}


#include <stdio.h>
#include <conio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
using namespace std;
int m, n;
struct node
{
	int c, d;
};
vector<node> v, v2, t, t2;
bool option(const node& a, const node& b)
{
	if (a.d < b.d)
		return true;
	else
		if (a.d == b.d && a.c < b.c)
			return true;
	return false;
}
void main()
{
	scanf_s("%d%d", &n, &m);
	t.resize(n);

	for (int i = 0; i < n; i++)
	{
		scanf_s("%d%d", &t[i].c, &t[i].d);
	}
	t2.resize(m);
	for (int i = 0; i < m; i++)
	{
		scanf_s("%d%d", &t2[i].c, &t2[i].d);
	}
	sort(t.begin(), t.end(), option);
	sort(t2.begin(), t2.end(), option);
	int kq = 0, j=0, kq2=0;
	for (int i = 0; i < n; i++)
	{
		while (j < m && t2[j].d < t[i].d)
		{
			v2.resize(v2.size() + 1);
			v2[v2.size() - 1] = t2[j];
			j++;

		}
		if (j == m)
		{
			v.resize(v.size() + 1);
			v[v.size() - 1] = t[i];
		}
		else
			if (t2[j].d == t[i].d)
			{
				while (j<m && t2[j].d==t[i].d && t2[j].c<t[i].c)
				{
					v2.resize(v2.size() + 1);
					v2[v2.size() - 1] = t2[j];
					j++;

				}
				if (j == m)
				{
					v.resize(v.size() + 1);
					v[v.size() - 1] = t[i];
				}
				else
				{
					if (t2[j].d > t[i].d)
					{
						v.resize(v.size() + 1);
						v[v.size() - 1] = t[i];
					}
					else
					{
						if (t2[j].c > t[i].c)
						{
							v.resize(v.size() + 1);
							v[v.size() - 1] = t[i];
						}
						else
						{
							j++;
							//kq++;
							kq2++;
						}

					}

				}
			}

	}
	if (j <= m - 1)
	{
		for (int i = j; i < m; i++)
		{
			v2.resize(v2.size() + 1);
			v2[v2.size() - 1] = t2[i];
		}
	}
	//========================================================================
	j = 0;
	kq = 0;
	for (int i = 0; i < n; i++)
	{
		while (j < m && t2[j].d < t[i].d)
			j++;
		if (j == m)
			break;
		else
			if (t2[j].d == t[i].d)
			{
				j++;
				kq++;

			}

	}
	/*for (int i = 0; i < v.size(); i++)
	{
		while (j < v2.size() && v2[j].d < v[i].d)
			j++;
		if (j == v2.size())
			break;
		else
			if (v2[j].d == v[i].d)
			{
				j++;
				kq++;
			}
	}*/

	printf("%d %d", kq, kq2);

	/*int j = 0, i=0, t=-1, kq=0, kq2=0;
	while (i < n && j < m)
	{
		while (j < m && v2[j].d < v[i].d)
			j++;
		if (j == m)
			break;
		else
			if (v2[j].d == v[i].d)
			{
				if (t==-1)
					t = j;
				while (t < m && v2[t].d == v[i].d && v2[t].c < v[i].c)
					t++;
				if (t == m)
				{
					i++;
					j++;
					kq++;
				}
				else
				{

				}

			}

	}
	*/

	//_getch();
}


#include <iostream>
#include <algorithm>

using namespace std;

struct pt{
	int a, b;
	bool operator < (pt a2)
	{
		return a < a2.a || (a == a2.a && b < a2.b);
	}
};
int main()
{
	pt marker[10000], cap[10000];
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> marker[i].a >> marker[i].b;
	sort(marker, marker + n);
	for (int i = 0; i < m; i++)
		cin >> cap[i].a >> cap[i].b;
	sort(cap, cap + m);
	int i = 0, j = 0, closed = 0, beautiful = 0;
	while(i < n && j < m)
	{
		if (marker[i].b < cap[j].b)
		{
			i++;
			continue;
		}
		if (cap[j].b < marker[i].b)
		{
			j++;
			continue;
		}
		closed++;
		if (cap[j].a == marker[i].a)
			beautiful++;
		else if (cap[j + 1].b == cap[j].b)
			j--;
		i++, j++;
	}
	cout << closed << " " << beautiful << endl;

}