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

#define int long long

#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;

template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

template<class A,class B>
ostream& operator<<(ostream& ost,const pair<A,B>&p){
	ost<<"{"<<p.first<<","<<p.second<<"}";
	return ost;
}

template<class T>
ostream& operator<<(ostream& ost,const vector<T>&v){
	ost<<"{";
	for(int i=0;i<v.size();i++){
		if(i)ost<<",";
		ost<<v[i];
	}
	ost<<"}";
	return ost;
}
struct Dinic{
    using F=long long;
    static const F INF=1ll<<50;

    struct Edge{
        int dst;
        F cap;
        int rev;
        Edge(int dst,F cap,int rev):dst(dst),cap(cap),rev(rev){}
    };

    int n;
    vector<vector<Edge>>G;
    vector<int>iter,level;
    Dinic(int n):n(n),G(n),iter(n),level(n){}
    inline void addEdge(int src,int dst,F cap){
        G[src].push_back(Edge(dst,cap,G[dst].size()));
        G[dst].push_back(Edge(src,0,G[src].size()-1));
    }
    inline void addUndirectedEdge(int src,int dst,F cap){
        G[src].push_back(Edge(dst,cap,G[dst].size()));
        G[dst].push_back(Edge(src,cap,G[src].size()-1));
    }

    void bfs(int s){
        level.assign(n,-1);
        queue<int>que;
        level[s]=0;
        que.push(s);
        while(que.size()){
            int u=que.front();
            que.pop();
            for(auto &e:G[u]){
                if(e.cap==0||level[e.dst]!=-1)continue;
                level[e.dst]=level[u]+1;
                que.push(e.dst);
            }
        }
    }

    F dfs(const int &s,const int &u,F cur){
        if(s==u)return cur;
        F sum=0;
        for(int &i=iter[u];i<G[u].size();i++){
            Edge &e=G[u][i],&ee=G[e.dst][e.rev];
            const int &v=e.dst;
            if(level[v]>=level[u]||ee.cap==0)continue;
            F f=dfs(s,v,min(cur-sum,ee.cap));
            if(f<=0)continue;
            ee.cap-=f;e.cap+=f;
            sum+=f;
            if(sum==cur)break;
        }
        return sum;
    }


    F maxFlow(int s,int t){
        F flow=0;
        while(true){
            bfs(s);
            if(level[t]==-1)return flow;
            iter.assign(n,0);
            flow+=dfs(s,t,INF);
        }
    }
};


int N,M;
int S[444],T[444];

const int V=400;

int calcMax(){
    vector<vint>lis(V);
    rep(i,N+M)lis[S[i]].pb(i);

    priority_queue<int,vint,greater<int>>que;
    int ans=0;
    for(int i=0;i<V;i++){
        for(auto k:lis[i])que.push(T[k]);
        while(que.size()&&que.top()<=i)que.pop();
        if(que.size()){
            ans++;
            que.pop();
        }
    }
    return ans;
}


int calcMin(){
    Dinic D(N+M+2*V+2);
    int src=N+M+2*V;
    int snk=src+1;

    rep(i,M)D.addEdge(src,i,1);
    rep(i,N)D.addEdge(M+i,snk,1);
    rep(i,V)D.addEdge(N+M+i,N+M+V+i,1);
    rep(i,M){
        for(int j=S[i];j<T[i];j++)D.addEdge(i,N+M+j,1);
    }
    rep(i,N){
        for(int j=S[i+M];j<T[i+M];j++)D.addEdge(N+M+V+j,M+i,1);
    }
    return D.maxFlow(src,snk);
}

signed main(){


    cin>>N>>M;
    N-=M;
    rep(i,N+M){
        cin>>S[i]>>T[i];
        S[i]--;
    }

    cout<<calcMax()<<endl;
    cout<<calcMin()<<endl;
    return 0;
}


Measured memory_bytes: 6236