#include<bits/stdc++.h>
using namespace std;
using Int = long long;
using ll = long long;

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

template<typename T> void drop(T x){cout<<x<<endl;exit(0);};

template<typename T, typename E>
struct SegmentTree{
  using F = function<T(T ,T)>;
  using G = function<T(T, E)>;
  using H = function<E(E, E)>;

  int n, height;
  F f;
  G g;
  H h;
  T ti;
  E ei;
  vector<T> dat;
  vector<E> laz;

  SegmentTree(F f, G g, H h, T ti, E ei):
    f(f), g(g), h(h), ti(ti), ei(ei){}

  void init(int n_){
    n = 1; height = 0;
    while(n < n_) n<<=1, height++;
    dat.assign(2*n, ti);
    laz.assign(2*n, ei);
  }

  void build(const vector<T> &v){
    int n_ = v.size();
    init(n_);
    for(int i=0;i<n_;i++) dat[n+i] = v[i];
    for(int i=n-1;i;i--)
      dat[i] = f(dat[(i<<1)|0], dat[(i<<1)|1]);
  }

  inline T reflect(int k){
    return laz[k] == ei? dat[k]:g(dat[k], laz[k]);
  }

  inline void eval(int k){
    if(laz[k] == ei) return;
    laz[(k<<1)|0] = h(laz[(k<<1)|0], laz[k]);
    laz[(k<<1)|1] = h(laz[(k<<1)|1], laz[k]);
    dat[k] = reflect(k);
    laz[k] = ei;
  }

  inline void thrust(int k){
    for(int i=height;i;i--) eval(k>>i);
  }

  inline void recalc(int k){
    while(k>>=1)
      dat[k] = f(reflect((k<<1)|0), reflect((k<<1)|1));
  }

  void update(int a, int b, E x){
    thrust(a += n);
    thrust(b += n-1);
    for(int l=a, r=b+1;l<r;l>>=1, r>>=1){
      if(l&1) laz[l] = h(laz[l], x), l++;
      if(r&1) --r, laz[r] = h(laz[r], x);
    }
    recalc(a);
    recalc(b);
  }

  void set_val(int a, T x){
    thrust(a += n);
    dat[a] = x; laz[a] = ei;
    recalc(a);
  }

  T query(int a, int b){
    thrust(a += n);
    thrust(b += n-1);
    T vl = ti, vr = ti;
    for(int l=a, r=b+1;l<r;l>>=1, r>>=1){
      if(l&1) vl = f(vl, reflect(l++));
      if(r&1) vr = f(reflect(--r), vr);
    }
    return f(vl, vr);
  }

};

#define F first
#define S second


signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  using pll = pair<ll,ll>;
  auto f1=[](ll a,ll b){return min(a,b);};
  auto f2=[](ll a,ll b){return a+b;};

  ll N,L;
  cin>>N>>L;
  vector<pll> A(N);
  map<ll,ll> M;
  ll cnt=0;
  const ll INF=N+100;
  for(auto &I:A){
    cin>>I.F>>I.S;
    M[I.F]=M[I.S]=0;
  }
  for(auto &I:M){I.S=cnt; cnt++;}
  for(auto &I:A){I.F=M[I.F]; I.S=M[I.S];}
  L=M[L];
  SegmentTree<ll,ll> dp(f1,f1,f1,INF,INF);
  SegmentTree<ll,ll> sumL(f2,f2,f2,0,0);
  SegmentTree<ll,ll> sumR(f2,f2,f2,0,0);
  dp.build(vector<ll>(cnt+100,INF));
  sumL.build(vector<ll>(cnt+100,0));
  sumR.build(vector<ll>(cnt+100,0));
  dp.update(0,1,0);
  sort(A.begin(),A.end());
  for(auto &I:A){
    ll x=dp.query(I.F,L+1);
    dp.update(I.S,I.S+1,x+1);
  }
  cout<<dp.query(L,L+1)<<" ";
  for(auto &I:A){
    sumL.update(I.F,I.F+1,1);
    sumR.update(I.S,I.S+1,1);
  }
  ll mx=0;
  for(ll i=0;i<=L;i++){
    ll c=sumL.query(i+1,L+10);
    if(i!=0){c+=sumR.query(0,i);}
    mx=max(mx,c);
  }
  cout<<mx+1<<endl;




  return 0;
}

