Problem: Problem Statement

You are given a list of $N$ intervals. The $i$-th interval is $[l_i, r_i)$, which denotes a range of numbers greater than or equal to $l_i$ and strictly less than $r_i$. In this task, you consider the following two numbers:

* The minimum integer $x$ such that you can select $x$ intervals from the given $N$ intervals so that the union of the selected intervals is $[0, L)$.
* The minimum integer $y$ such that for all possible combinations of $y$ intervals from the given $N$ interval, it does cover $[0, L)$.



We ask you to write a program to compute these two numbers.

* * *

Input

The input consists of a single test case formatted as follows.

> $N$ $L$ $l_1$ $r_1$ $l_2$ $r_2$ $\vdots$ $l_N$ $r_N$

The first line contains two integers $N$ ($1 \leq N \leq 2 \times 10^5$) and $L$ ($1 \leq L \leq 10^{12}$), where $N$ is the number of intervals and $L$ is the length of range to be covered, respectively. The $i$-th of the following $N$ lines contains two integers $l_i$ and $r_i$ ($0 \leq l_i < r_i \leq L$), representing the range of the $i$-th interval $[l_i, r_i)$. You can assume that the union of all the $N$ intervals is $[0, L)$

Output

Output two integers $x$ and $y$ mentioned in the problem statement, separated by a single space, in a line.

Examples

Input| Output
---|---


3 3
0 2
1 3
1 2


|


2 3



2 4
0 4
0 4


|


1 1



5 4
0 2
2 4
0 3
1 3
3 4


|


2 4






Example

Input




Output

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define inf (int)(1e18)

template<typename M>
struct segment_tree{
	typedef function<M(M, M)> F;
	int size;
	vector<M> val;
	F f;
	M e;

	segment_tree(int N, vector<M> &data, F f, M e) : f(f), e(e){
		size = 1;
		while(size < N) size *= 2;
		val.assign(2 * size, e);
		for(int i = 0; i < N; i++) val[size + i] = data[i];
		for(int i = 0; i < size; i++) val[size + i] = e;
		for(int i = size - 1; i > 0; i--) val[i] = f(val[2 * i], val[2 * i + 1]);
	}

	void update(int k, M x){
		k += size;
		val[k] = x;
		while(k /= 2) val[k] = f(val[2 * k], val[2 * k + 1]);
	}

	M query(int l, int r){
		M L = e, R = e;
		for(l += size, r += size; l < r; l /= 2, r /= 2){
			if(l & 1) L = f(L, val[l++]);
			if(r & 1) R = f(val[--r], R);
		}
		return f(L, R);
	}
};

int mini(int a, int b){
	return a <= b ? a : b;
}

signed main(){
	int N, L, i, j;
	scanf("%lld%lld", &N, &L);
	vector<int> l(N), r(N);
	vector<int> event(0);
	for(i = 0; i < N; i++){
		scanf("%lld%lld", &l[i], &r[i]);
		event.push_back(l[i]);
		event.push_back(r[i]);
	}
	sort(event.begin(), event.end());
/*	for(i = 1, j = 1; j < 2 * N; j++){
		if(event[j] != event[j - 1]){
			event[i] = event[j];
			i++;
		}
	}
	event.erase(event.begin() + i, event.end());
*/	L = 0;
	for(i = 0; i < N; i++){
		l[i] = lower_bound(event.begin(), event.end(), l[i]) - event.begin();
		r[i] = lower_bound(event.begin(), event.end(), r[i]) - event.begin();
		L = max(L, r[i]);
	}
/*	printf("L = %lld\n", L);
	for(i = 0; i < N; i++){
		printf("(%lld, %lld)\n", l[i], r[i]);
	}
*/	vector<vector<int>> corl(L + 1, vector<int>(0));
	for(i = 0; i < N; i++){
		corl[r[i]].push_back(l[i]);
	}
	vector<int> data(L + 1, inf);
//	data[0] = 0;
	segment_tree<int> dp(L + 1, data, mini, inf);
	dp.update(0, 0);
//	printf("dp[0] = %lld\n", dp.query(0, 1));
	for(i = 1; i <= L; i++){
//		printf("i = %lld\n", i);
		int now = inf;
		for(j = 0; j < corl[i].size(); j++){
//			printf("corl[i][%lld]\n", corl[i][j]);
			now = min(now, dp.query(corl[i][j], i) + 1);
		}
//		printf("test3\n");
		dp.update(i, now);
//		printf("%lld\n", dp.query(i, i + 1));
	}
//	printf("test5\n");
	printf("%lld ", dp.query(L, L + 1));

	vector<int> A(L + 1, 0);
	for(i = 0; i < N; i++){
		A[l[i]]++;
		A[r[i]]--;
	}
	int minA = A[0];
	for(i = 1; i < L; i++){
		A[i] += A[i - 1];
		minA = min(minA, A[i]);
	}
/*	for(i = 0; i <= L; i++){
		printf("A[%lld] = %lld\n", i, A[i]);
	}
*/	printf("%lld\n", N - minA + 1);
	return 0;
}