Vasya has got an undirected graph consisting of $n$ vertices and $m$ edges. This graph doesn't contain any self-loops or multiple edges. Self-loop is an edge connecting a vertex to itself. Multiple edges are a pair of edges such that they connect the same pair of vertices. Since the graph is undirected, the pair of edges $(1, 2)$ and $(2, 1)$ is considered to be multiple edges. Isolated vertex of the graph is a vertex such that there is no edge connecting this vertex to any other vertex.

Vasya wants to know the minimum and maximum possible number of isolated vertices in an undirected graph consisting of $n$ vertices and $m$ edges. 


-----Input-----

The only line contains two integers $n$ and $m~(1 \le n \le 10^5, 0 \le m \le \frac{n (n - 1)}{2})$.

It is guaranteed that there exists a graph without any self-loops or multiple edges with such number of vertices and edges.


-----Output-----

In the only line print two numbers $min$ and $max$ — the minimum and maximum number of isolated vertices, respectively.


-----Examples-----
Input
4 2

Output
0 1

Input
3 1

Output
1 1



-----Note-----

In the first example it is possible to construct a graph with $0$ isolated vertices: for example, it should contain edges $(1, 2)$ and $(3, 4)$. To get one isolated vertex, we may construct a graph with edges $(1, 2)$ and $(1, 3)$. 

In the second example the graph will always contain exactly one isolated vertex.

Difficulty: EASY
Tags: Graph algorithms

Constructive algorithms

Starter code:

Solutions:
from math import *
(n, m) = map(int, input().split())
min = n - 2 * m
max = n
if m > 0:
	x = ceil((1 + sqrt(1 + 8 * m)) / 2)
	max -= x
if min < 0:
	min = 0
if max < 0:
	max = 0
print(min, max)


(n, m) = map(int, input().split())
minimum = max(0, n - 2 * m)
maximum = 0
for i in range(0, n + 1):
	if i * (i - 1) // 2 >= m:
		maximum = n - i
		break
print(minimum, maximum)


(n, m) = map(int, input().split())
min_ = max(0, n - 2 * m)
left = min_
right = n + 1
while left + 1 < right:
	mid = (left + right) // 2
	x = n - mid
	if x * (x - 1) // 2 >= m:
		left = mid
	else:
		right = mid
print(min_, left)


import math
(n, m) = map(int, input().split())
ans1 = max(n - m * 2, 0)
tmp = math.sqrt(1 + 8 * m)
ans2 = math.ceil((tmp + 1) / 2)
if m == 0:
	ans2 = 0
ans2 = n - ans2
print(ans1, ' ', ans2)


import sys
import math
import cmath
(n, m) = list(map(int, sys.stdin.readline().strip().split()))
x = max(0, n - 2 * m)
c = -1 * (2 * m)
d = 1 - 4 * c
sol1 = (1 - math.sqrt(d)) / 2
sol2 = (1 + math.sqrt(d)) / 2
sol = []
if sol1 >= 0:
	sol.append(sol1)
if sol2 >= 0:
	sol.append(sol2)
if len(sol) > 0:
	solmin = min(sol)
else:
	print('error in logic')
y = int(max(0, n - solmin))
print(x, y)


(n, m) = list(map(int, input().split()))
if m == 0:
	Min = n
	Max = n
else:
	Min = 0 if m >= (n // 2 if n % 2 == 0 else n // 2 + 1) else n - m * 2
	for i in range(n, 0, -1):
		nEdges = i * (i - 1) // 2
		if nEdges == m:
			Max = n - i
			break
		elif nEdges < m:
			Max = n - i - 1
			break
print(Min, Max)


s = input().split()
n = int(s[0])
m = int(s[1])
ans = 0
while ans * (ans - 1) / 2 < m:
	ans += 1
print(max(0, n - m * 2), n - ans)


(n, m) = map(int, input().split())
mi = n - 2 * m
if mi < 0:
	mi = 0
mc = -1
if m == 0:
	mc = 0
elif m == 1:
	mc = 2
else:
	for i in range(2, 10 ** 5):
		if i * (i - 1) // 2 <= m and i * (i + 1) // 2 >= m:
			mc = i + 1
			break
print(mi, n - mc)


(n, m) = [int(i) for i in input().split()]
if m == 0:
	print('%d %d' % (n, n))
	exit()
if m == 1:
	r = max(0, n - 2)
	print('%d %d' % (r, r))
	exit()
z = 1
cur = max(0, n - 2)
add = 2
while z < m:
	z += add
	add += 1
	cur -= 1
print('%d %d' % (max(0, n - 2 * m), cur))


(n, m) = map(int, input().split())
idx = 0
while idx * (idx - 1) // 2 < m:
	idx += 1
print(max(0, n - m * 2), max(0, n - idx))


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	return
if m == n * (n - 1) // 2:
	print(0, 0)
	return
L = 0
R = n + 1
while R - L > 1:
	m1 = (L + R) // 2
	if m1 * (m1 - 1) // 2 < m:
		L = m1
	else:
		R = m1
ans_max = n - R
ans_min = max(0, n - 2 * m)
print(ans_min, ans_max)


(n, m) = map(int, input().split())
vs = n * (n - 1) // 2
mn = mx = 0
if m == 0:
	print(n, n)
else:
	if m * 2 >= n:
		mn = 0
	else:
		mn = n - m * 2
	q = n - 1
	h = -1
	while m <= vs:
		vs -= q
		q -= 1
		h += 1
	mx = h
	print(mn, mx)


import string
line = input()
line2 = line.split()
n = int(line2[0])
m = int(line2[1])
k = n // 2 + n % 2
if k <= m:
	minN = 0
else:
	minN = n - 2 * m
k = 0
maxN = m
for i in range(n):
	k = k + i
	if k >= m:
		maxN = n - i - 1
		if i == 0:
			maxN += 1
		break
print(minN, maxN)


import math
(n, m) = list(map(int, input().split()))
if n == 1:
	print(1, 1)
elif m == 0:
	print(n, n)
else:
	mi = 0
	if m < (n + 1) / 2:
		mi = n - 2 * m
	ma = n - int(math.ceil(0.5 + (1 + 8 * m) ** 0.5 * 0.5))
	print(mi, ma)


(n, k) = map(int, input().split())
for i in range(n + 1):
	if i * (i - 1) // 2 >= k:
		exit(print(max(n - k * 2, 0), n - i))


import math
from functools import reduce
(n, m) = map(int, input().split())
if m > 0:
	mx = 0
	for i in range(2, n + 1):
		t = i * (i - 1) // 2
		q = (i - 1) * (i - 2) // 2
		if m > t:
			continue
		else:
			sisa = m - q
			mx = n - i if sisa > 0 else n - (i - 1)
			break
	mn = 0 if n <= 2 * m else n - 2 * m
else:
	mn = mx = n
print(mn, mx)


import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit(0)
otv1 = n - m * 2
if otv1 < 0:
	otv1 = 0
otv2 = (1 + math.sqrt(1 + 8 * m)) / 2
if otv2 % 1 != 0:
	otv2 = otv2 // 1 + 1
otv2 = int(n - otv2)
if otv2 < 0:
	otv2 = 0
print(otv1, otv2)


(n, m) = map(int, input().split())
minA = max(0, n - 2 * m)
curC = 0
curE = 0
curMax = curC * (curC - 1) // 2
while m > 0:
	if m > curMax - curE:
		m -= curMax - curE
		curE = curMax
		curC += 1
		curMax = curC * (curC - 1) // 2
	elif m == curMax - curE:
		break
	else:
		break
maxA = n - curC
print(str(minA) + ' ' + str(maxA))


from math import ceil
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	print(max(0, n - 2 * m), n - ceil((1 + (1 + 8 * m) ** 0.5) / 2))


(n, m) = map(int, input().split())
n_min = n - m * 2
if n_min < 0:
	n_min = 0
if m == 0:
	n_occ = 0
elif m == 1:
	n_occ = 2
elif m == 2:
	n_occ = 3
else:
	left = 0
	right = 100007
	while left < right:
		mid = (left + right) // 2
		if mid * (mid - 1) // 2 < m:
			left = mid + 1
		else:
			right = mid
	if left * (left - 1) // 2 > m:
		left -= 1
	n_occ = left
	if n_occ * (n_occ - 1) // 2 < m:
		n_occ += 1
n_max = n - n_occ
n_max = max(n_max, 0)
print(n_min, n_max)


from sys import stdin, stdout

def main():
	(n, m) = map(int, stdin.readline().split())
	clique = 1
	rem = m
	while rem > 0:
		d = min(clique, rem)
		clique += 1
		rem -= d
	res = n
	if clique > 1:
		res = n - clique
	stdout.write('%d %d' % (max(0, n - 2 * m), res))
main()


def main():
	(n, m) = str.split(input())
	n = int(n)
	m = int(m)
	if 2 * m >= n:
		Min = 0
	else:
		Min = n - 2 * m
	cnt = 0
	if m == 0:
		Max = n
	else:
		for i in range(1, n):
			cnt += i
			if cnt >= m:
				Max = n - i - 1
				break
	print(Min, Max)
main()


(n, m) = tuple([int(x) for x in input().split()])
(min, max) = (0, 0)
if n <= 2 * m:
	min = 0
else:
	min = n - 2 * m
(c, r) = (1, m)
while r > 0:
	d = c if c < r else r
	r = r - d
	c += 1
max = n
if c > 1:
	max = n - c
print(min, max)


def f(l=0, r=int(1000000.0)):
	if r - l <= 1:
		return r
	mid = (l + r) // 2
	if mid * (mid - 1) // 2 >= m:
		return f(l, mid)
	else:
		return f(mid, r)
(n, m) = map(int, input().split())
print(n - m * 2 if m <= n // 2 else 0, n - f() if m else n)


(n, m) = map(int, input().split())
max_v = 0
for i in range(1, n):
	if m <= i * (i - 1) // 2:
		max_v = n - i
		break
if m == 0:
	max_v = n
if n <= m * 2:
	min_v = 0
else:
	min_v = n - 2 * m
print(min_v, max_v)


(v, e) = list(map(int, input().split()))
la = v
fa = e
for x in range(e):
	if v <= 0:
		break
	else:
		v -= 2
if v <= 0:
	kam = 0
else:
	kam = v
v = la
e = fa
ti = 2
dim = 1
for x in range(5555555):
	if e != 0 and v > 0:
		if dim >= e:
			v -= ti
			break
		ti += 1
		dim += ti - 1
	else:
		break
if v <= 0:
	sam = 0
else:
	sam = v
print(kam, sam)


import sys
from math import *

def minp():
	return sys.stdin.readline().strip()
(n, m) = list(map(int, minp().split()))
k = int(sqrt(m))
while k * (k - 1) // 2 > m:
	k -= 1
while k * (k - 1) // 2 < m:
	k += 1
print(max(0, n - m * 2), n - k)


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	(s, n1) = (1, 0)
	while n1 < m:
		n1 += s
		s += 1
	print(max(0, n - 2 * m), n - s)


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	for i in range(n + 1):
		if i * (i + 1) // 2 >= m:
			print(max(0, n - 2 * m), n - i - 1)
			exit()


(v, e) = map(int, input().split())
min = max(0, v - 2 * e)
n = 0
while n * (n - 1) // 2 < e:
	n += 1
max = v - n
print(min, max)


(n, m) = map(int, input().split())
if m == 0:
	from sys import exit
	print(n, n)
	exit()
x = max(0, n - 2 * m)
if m == 1:
	print(x, n - 2)
elif m == 2:
	print(x, n - 3)
else:
	q = 2 * m
	for i in range(1, m + 2):
		if q < i * (i - 1):
			break
	i -= 1
	a = m - i * (i - 1) // 2
	(u, p) = (a // i, a % i)
	if p > 0:
		u += 1
	print(x, n - i - u)


(n, m) = map(int, input().split())
minV = max(0, n - m * 2)
(l, r) = (0, n)
while l < r:
	mid = (l + r) // 2
	k = mid * (mid - 1) // 2
	if k < m:
		l = mid + 1
	else:
		r = mid
maxV = max(0, n - l)
print(minV, maxV)


import math

def find_min_discrete_connected_vertices(m):
	return math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)

def main():
	(n, m) = input().split()
	n = int(n)
	m = int(m)
	max_discrete_connected_vertices = m * 2
	min = 0 if max_discrete_connected_vertices >= n else n - max_discrete_connected_vertices
	max = None
	if m == 0:
		max = n
	else:
		min_discrete_connected_vertices = find_min_discrete_connected_vertices(m)
		max = n - min_discrete_connected_vertices
	print(min, max)
main()


(a, b) = map(int, input().split())
minn = max(0, a - 2 * b)
maxx = int(0)
while maxx * (maxx - 1) // 2 < b:
	maxx += 1
maxx = max(0, a - maxx)
print(minn, maxx)


(n, m) = map(int, input().strip().split())
k = 0
for i in range(0, n + 1):
	k = i
	if k * (k - 1) / 2 >= m:
		break
print(max(0, n - m * 2), n - k)


(n, m) = list(map(int, input().split()))
min = n - m * 2
for i in range(1, n + 1):
	x = i * (i - 1) / 2
	if x >= m:
		break
max = n - i
if min < 0:
	min = 0
if m == 0:
	max = n
print(min, max)


(n, m) = list(map(int, input().split()))
mn = max(n - 2 * m, 0)
mxa = 0
while mxa * (mxa - 1) < 2 * m:
	mxa += 1
print(mn, n - mxa)


(n, m) = list(map(int, input().split()))
(l, r) = (0, n)
while l < r:
	c = (l + r) // 2
	if c * (c - 1) // 2 < m:
		l = c + 1
	else:
		r = c
mn = 0
if m <= n // 2:
	mn = n - m * 2
print(mn, n - l)


from math import sqrt, ceil

def main():
	(n, m) = map(int, input().split())
	print(max(n - m * 2, 0), n - ceil(0.5 + sqrt(0.25 + 2.0 * m)) if m else n)
main()


(n, m) = map(int, input().split())
print(max(n - 2 * m, 0), (n, int(n - (1 + (8 * m + 1) ** 0.5) / 2))[m > 0])


import math
(n, m) = [int(i) for i in input().split()]
k1 = n
if m != 0:
	k1 = n - math.ceil((1 + (1 + 8 * m) ** 0.5) / 2)
k2 = 0
if m <= n / 2:
	k2 = n - m * 2
print(k2, k1)


(n, m) = map(int, input().split())
t = 0
while t * (t - 1) // 2 < m:
	t += 1
minm = max(0, n - 2 * m)
print(minm, max(0, n - t))


(n, m) = map(int, input().split())
if n == 1:
	print('1 1')
	exit()
if m == 0:
	print('%d %d' % (n, n))
	exit()
Min = max(0, n - m * 2)
cnt = 2
while m > cnt * (cnt - 1) / 2:
	cnt += 1
Max = n - cnt
print('%d %d' % (Min, Max))


def abcd(su):
	return su * (su - 1) // 2
(n, m) = map(int, input().split())
if 2 * m >= n:
	print('0', end=' ')
else:
	print(n - 2 * m, end=' ')
if m <= 2:
	if m == 2:
		exit(print(n - 3))
	elif m == 1:
		exit(print(n - 2))
	else:
		exit(print(n))
else:
	su = 2
	while abcd(su) < m:
		su += 1
	print(n - su)


import math
(n, m) = [int(x) for x in input().split()]
ma = max(0, n - 2 * m)
k = 1
l = 1
j = 1
if m == 0:
	print(n, n)
else:
	d = math.sqrt(8 * m) + 1
	d = d / 2
	k = math.ceil(d)
	mi = max(0, n - 2 * m)
	ma = max(0, n - k)
	print(mi, ma)


(n, m) = map(int, input().split())
cur = 1
rem = m
while rem > 0:
	d = min(cur, rem)
	rem -= d
	cur += 1
res = n
if cur > 1:
	res = n - cur
print(max(0, n - m * 2), res)


import math
(n, m) = map(int, input().split())
min_r = n - 2 * m
if min_r < 0:
	min_r = 0
if m > 0:
	D = 1 + 4 * 2 * m
	D = math.ceil(D ** 0.5)
	n_now = math.ceil((1 + D) / 2)
	max_r = n - n_now
else:
	max_r = min_r
print(min_r, max_r)


(n, m) = map(int, input().split())
ans2 = 0
if (n + 1) // 2 > m:
	print(n - m * 2, end=' ')
else:
	print(0, end=' ')
for i in range(n, -1, -1):
	now = n - i
	if now * (now - 1) // 2 >= m:
		print(i)
		break


import math
(n, m) = map(int, input().split())
minv = n - 2 * m if n >= 2 * m else 0
maxv = minv
prek = int((1 + math.sqrt(1 + 8 * m)) / 2)
for i in range(prek - 3, prek + 3):
	if m <= i * (i - 1) / 2 and i >= 0:
		maxv = max(n - i, maxv)
print(minv, maxv)


(n, m) = map(int, input().split())
if m >= n / 2:
	minRet = 0
else:
	minRet = n - 2 * m
i = 1
while i * (i - 1) / 2 < m:
	i += 1
i -= 1
if i * (i - 1) / 2 == m:
	addVal = 0
else:
	addVal = 1
maxRet = n - i - addVal
print(str(minRet) + ' ' + str(maxRet))


read = input().split(' ')
n = int(read[0])
m = int(read[1])
b = 0
while b < n and b * (b - 1) / 2 < m:
	b += 1
ans1 = n - m * 2
if ans1 < 0:
	ans1 = 0
ans2 = n - b
print(ans1, ans2)


(n, m) = [int(x) for x in input().split()]
minimum = max(0, n - 2 * m)
mx = 0
for i in range(n):
	if i * (i - 1) // 2 >= m:
		mx = n - i
		break
print(minimum, mx)


(n, m) = [int(x) for x in input().split()]
e = n // 2
if n % 2 != 0:
	e += 1
mn = max(0, e - m)
mn *= 2
if n % 2 != 0:
	mn -= 1
mn = max(0, mn)
for i in range(n + 1):
	if i * (i - 1) // 2 >= m:
		mx = n - i
		break
print(str(mn) + ' ' + str(mx))


import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit(0)
a = max(0, n - 2 * m)
b = math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
print(a, int(n - b))


def Bin(n, key):
	l = -1
	r = n + 1
	while l + 1 < r:
		m = (l + r) // 2
		if m * (m - 1) // 2 < key:
			l = m
		else:
			r = m
	return r
(n, m) = map(int, input().split())
print(max(0, n - m * 2), n - Bin(n, m))


from math import ceil
(n, m) = list(map(int, input().split()))
minn = n // 2 + n % 2
if m >= minn:
	ans1 = 0
else:
	ans1 = n - m * 2
if m == 0:
	ans2 = n
else:
	ans2 = n - ceil((1 + (1 + 8 * m) ** 0.5) / 2)
print(ans1, ans2)


(n, m) = map(int, input().split())
if n / 2 <= m:
	print(0, end=' ')
else:
	print(n - 2 * m, end=' ')
from math import ceil as upar_wale, sqrt as S
z = upar_wale((1 + S(1 + 8 * m)) / 2)
print(n - z if m != 0 else n)


(n, m) = map(int, input().split())
min_ = max(0, n - m * 2)
if m == 0:
	print(min_, n)
else:
	sum = 0
	for i in range(1, n + 1):
		sum += i - 1
		if sum >= m:
			print(min_, n - i)
			break


(n, m) = map(int, input().split())
if n // 2 + n % 2 <= m:
	_min = 0
else:
	_min = n - 2 * m
tmp = 0
for i in range(n + 1):
	if i * (i - 1) >= 2 * m:
		tmp = i
		break
_max = n - tmp
print(_min, _max)


a = input().split()
n = int(a[0])
m = int(a[1])
if m != 0:
	print(max(n - 2 * m, 0), max(int(n - (1 + (1 + 8 * m) ** 0.5) / 2), 0))
else:
	print(max(n - 2 * m, 0), n)


import math
(n, m) = map(int, input().split(' '))
a = min(n, 2 * m)
b = math.ceil(0.5 * (1 + pow(1 + 8 * m, 0.5)))
if m == 0:
	b = 0
print(n - a, n - b)


(n, m) = map(int, input().split())
print(max(0, n - 2 * m), end=' ')
l = -1
r = n + 1
while r - l > 1:
	s = (l + r) // 2
	if s * (s - 1) < 2 * m:
		l = s
	else:
		r = s
print(max(0, n - r))


from __future__ import division, print_function
import collections

def main():
	import sys
	(n, m) = list(map(int, input().split()))
	ma = n
	if m == 0:
		ma = n
	else:
		ma = n - 1
		t = 0
		for i in range(1, n):
			t += i
			ma -= 1
			if t >= m:
				break
	mi = max(0, n - 2 * m)
	print('%d %d\n' % (mi, ma))
	return 0
main()


(n, m) = [int(x) for x in input().split()]
if n % 2 == 0:
	if m >= n // 2:
		min_ = 0
	else:
		min_ = n - m * 2
elif m >= n // 2 + 1:
	min_ = 0
else:
	min_ = n - m * 2
for i in range(100005):
	if i * (i - 1) / 2 >= m:
		max_ = n - i
		break
print('%d %d' % (min_, max_))


def ii():
	return int(input())

def mi():
	return list(map(int, input().split()))

def li():
	return list(mi())
(n, m) = mi()
x = max(0, n - 2 * m)
for i in range(n + 1):
	c = i * (i - 1) // 2
	if c >= m:
		y = n - i
		break
print(x, y)


(n, m) = map(int, input().split())
if n <= m * 2:
	min_var = 0
else:
	min_var = n - m * 2
k = 0
while True:
	if k * (k - 1) // 2 >= m:
		break
	k += 1
print(min_var, n - k)


(n, m) = map(int, input().split())
min_ans = n - min(n, m * 2)
max_ans = 0
if m > 0:
	i = 2
	m -= 1
	while m > 0:
		m -= i
		i += 1
	max_ans = n - i
else:
	max_ans = n
print(min_ans, max_ans)


(n, m) = map(int, input().split())
amin = max(n - m * 2, 0)
amax = 0
if m == 0:
	amax = n
else:
	for i in range(2, 100001):
		kc2 = i * (i - 1) // 2
		if kc2 >= m:
			amax = n - i
			break
print(amin, amax)


(n, m) = map(int, input().split())
from math import *

def func(n):
	return n * (n - 1) // 2
if m == 0:
	print(n, end=' ')
else:
	print(max(0, n - m * 2), end=' ')
flag = 0
answer = n
for j in range(n, -1, -1):
	if func(j) < m:
		answer = n - j - 1
		flag = 1
		break
print(answer)


import math
(n, m) = (int(i) for i in input().split())
(m1, m2) = (0, 0)
if m == 0:
	print(n, n)
else:
	if m < math.ceil(n / 2):
		m1 = n - 2 * m
	for i in range(1, n + 1):
		if m <= i * (i - 1) // 2:
			m2 = i
			break
	print(m1, n - m2)


(n, m) = map(int, input().split())
Min = 0
temp = n // 2 + n % 2
if temp > m:
	Min = n - m * 2
Max = 0
n1 = 0
while n1 * (n1 - 1) // 2 < m:
	n1 += 1
if n1 < n:
	Max = n - n1
print(Min, Max)


d = list(map(int, input().split(' ')))
mn = d[0] - d[1] * 2
if mn < 0:
	mn = 0
n = 1
s = 0
while s < d[1]:
	s += n
	n += 1
if d[1] == 0:
	n = 0
print(mn, d[0] - n)


import sys
import math
import itertools
import functools
import collections

def ii():
	return int(input())

def mi():
	return map(int, input().split())

def li():
	return list(map(int, input().split()))

def lcm(a, b):
	return abs(a * b) // math.gcd(a, b)

def wr(arr):
	return ' '.join(map(str, arr))

def revn(n):
	return str(n)[::-1]

def dd():
	return collections.defaultdict(int)

def ddl():
	return collections.defaultdict(list)

def sieve(n):
	if n < 2:
		return list()
	prime = [True for _ in range(n + 1)]
	p = 3
	while p * p <= n:
		if prime[p]:
			for i in range(p * 2, n + 1, p):
				prime[i] = False
		p += 2
	r = [2]
	for p in range(3, n + 1, 2):
		if prime[p]:
			r.append(p)
	return r

def divs(n, start=1):
	r = []
	for i in range(start, int(math.sqrt(n) + 1)):
		if n % i == 0:
			if n / i == i:
				r.append(i)
			else:
				r.extend([i, n // i])
	return r

def divn(n, primes):
	divs_number = 1
	for i in primes:
		if n == 1:
			return divs_number
		t = 1
		while n % i == 0:
			t += 1
			n //= i
		divs_number *= t

def prime(n):
	if n == 2:
		return True
	if n % 2 == 0 or n <= 1:
		return False
	sqr = int(math.sqrt(n)) + 1
	for d in range(3, sqr, 2):
		if n % d == 0:
			return False
	return True

def convn(number, base):
	newnumber = 0
	while number > 0:
		newnumber += number % base
		number //= base
	return newnumber

def cdiv(n, k):
	return n // k + (n % k != 0)
(n, m) = mi()
if m == 0:
	print(n, n)
else:
	print(max(0, n - 2 * m), n - math.ceil(0.5 + math.sqrt(2 * m + 0.25)))


(n, m) = map(int, input().split())
e = n // 2 + int(n % 2)
mi = max(0, 2 * (e - m) - int(n % 2))
s = 0
i = 0
while s < m:
	i += 1
	s += i
ma = n - i - 1
if m == 0:
	ma += 1
print(mi, ma)


import math

def get_input_list():
	return list(map(int, input().split()))
(n, m) = get_input_list()
if m == 0:
	print(n, n)
else:
	a = max(0, n - 2 * m)
	b = max(0, n - math.ceil((1 + math.sqrt(1 + 8 * m)) / 2))
	print(a, b)


import sys
import math
fileoperation = 0
if fileoperation:
	orig_stdout = sys.stdout
	orig_stdin = sys.stdin
	inputfile = open('W:/Competitive Programming/input.txt', 'r')
	outputfile = open('W:/Competitive Programming/output.txt', 'w')
	sys.stdin = inputfile
	sys.stdout = outputfile
mod = 1000000007

def nospace(l):
	ans = ''.join((str(i) for i in l))
	return ans
t = 1
for tt in range(t):
	(n, m) = map(int, sys.stdin.readline().split(' '))
	ans = 0
	k = 0
	for i in range(100000000000):
		ans += i
		if ans >= m:
			k += 1
			break
		k += 1
	if m:
		print(max(0, n - 2 * m), n - k)
	elif m == 0:
		print(n, n)
if fileoperation:
	sys.stdout = orig_stdout
	sys.stdin = orig_stdin
	inputfile.close()
	outputfile.close()


import math
(a, b) = [int(i) for i in input().split()]
n = a - b * 2
if n <= 0:
	print(0, end=' ')
else:
	print(n, end=' ')
if b == 0:
	print(a, end=' ')
else:
	r = math.ceil((-1 + math.sqrt(1 + 8 * b)) / 2) + 1
	n = a - r
	if n <= 0:
		print(0, end=' ')
	else:
		print(n, end=' ')


import math
import sys
from collections import defaultdict
from collections import Counter
from collections import deque
import bisect
input = iter(sys.stdin.buffer.read().decode().splitlines()).__next__
ilele = lambda : map(int, input().split())
alele = lambda : list(map(int, input().split()))

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]
INF = 10 ** 18
MOD = 10 ** 9 + 7
(n, m) = ilele()
if n == 1:
	print(1, 1)
elif m == 0:
	print(n, n)
elif n == 2:
	print(0, 0)
else:
	x = math.ceil(n / 2)
	if x <= m:
		xx = 0
	else:
		xx = max(0, n - 2 * m)
	yy = 0
	for i in range(2, n + 1):
		y = i * (i - 1) // 2
		if y >= m:
			yy = i
			break
	print(xx, n - yy)


from sys import exit
(n, m) = map(int, input().split())
ans1 = max(0, n - 2 * m)
k = 0
if m == 0:
	print(ans1, n)
	exit(0)
cnt = 1
for i in range(1, n + 1):
	if k + i <= m:
		cnt += 1
		k += i
	else:
		if k != m:
			cnt += 1
		break
ans2 = max(0, n - cnt)
print(ans1, ans2)


def main():
	(n, m) = map(int, input().split())
	minimum = max(0, n - 2 * m)
	k = 0
	while m >= k * (k - 1) // 2:
		k += 1
	k -= 1
	if k == 1:
		maximum = n
	else:
		maximum = n
		m -= k * (k - 1) // 2
		maximum -= k
		while m > 0:
			k += 1
			m -= k
			maximum -= 1
	print(minimum, maximum)
main()


(n, m) = map(int, input().split())
mn = n - min(2 * m, n)
k = 0
while k * (k - 1) // 2 < m:
	k += 1
mx = n - k
print(str(mn) + ' ' + str(mx))


import sys
(n, m) = [int(i) for i in str(sys.stdin.read()).split()]
mini = max(0, n - 2 * m)
l = 0
while True:
	if l * (l - 1) >= 2 * m:
		break
	l += 1
maxi = n - l
print(mini, maxi)


(n, m) = map(int, input().split())
minimum = n - 2 * m
if minimum < 0:
	minimum = 0
edges = m
verts = 1
while edges > 0:
	if verts < edges:
		edges -= verts
		verts += 1
	else:
		edges = 0
		verts += 1
maximum = n - verts
if verts == 1:
	maximum = n
print(minimum, maximum)


(ver, rebra) = [int(i) for i in input().split()]
min_ = max(ver - rebra * 2, 0)
cnt = 1
max_ = 2
for i in range(2, rebra + 1000):
	if cnt >= rebra:
		break
	cnt += i
	max_ += 1
if rebra == 0:
	max_ = 0
if rebra == 1:
	max_ = 2
print(min_, ver - max_)


(n, m) = map(int, input().split())
(mi, mx) = (0, 0)
for i in range(2, n + 1):
	if i * (i - 1) // 2 <= m:
		mx = i
if mx * (mx - 1) // 2 < m:
	mx += 1
mi = max(0, n - m * 2)
print(mi, n - mx)


import math
(n, e) = map(int, input().split())
y = 0
if e > 0:
	k = math.sqrt(1 + 8 * (e - 1))
	k1 = (1 + k) // 2 + 1
	k2 = n - k1
	k3 = n - e * 2
	k4 = max(k3, 0)
	k5 = max(int(k2), 0)
	print(int(k4), int(k5))
else:
	print(n, n)


import math
import collections
import bisect
import heapq
import time
import random
import itertools
import sys
(N, M) = map(int, input().split())
if M == 0 or N == 1:
	print(N, N)
else:
	n = 1
	while n * (n - 1) < 2 * M:
		n += 1
	vmax = max(N - n, 0)
	vmin = max(N - 2 * M, 0)
	print(vmin, vmax)


def main():
	(n, m) = map(lambda x: int(x), input().split(' '))
	min_ans = max(0, n - m * 2)
	max_ans = n
	for i in range(n):
		if i * (i - 1) / 2 >= m:
			break
		max_ans -= 1
	print(min_ans, max_ans)
main()


while True:
	try:
		if __name__ == '__main__':
			(v, e) = map(int, input().split())
			if e == 0:
				print(v, v)
			else:
				mv = mxv = 0
				if e * 2 >= v:
					mv = 0
				else:
					mv = v - e * 2
				for i in range(1, v + 1, 1):
					t = i * (i - 1) // 2
					if t >= e:
						mxv = i
						break
				print(mv, v - mxv)
	except EOFError:
		break


masukan = [int(item) for item in input().split(' ')]
n = masukan[0]
m = masukan[1]

def getMin():
	if n / m <= 2:
		return 0
	else:
		return n - m * 2

def getMax():
	numEdge = 0
	for i in range(2, n + 1):
		if numEdge < m:
			numPosEdge = i * (i - 1) / 2
			numEdge = numPosEdge
		else:
			return n - (i - 1)
	return n - i
if n == 0:
	print(0, 0)
elif m == 0:
	print(n, n)
elif m >= n * (n - 1) / 2:
	print(0, 0)
else:
	print(getMin(), getMax())


def STR():
	return list(input())

def INT():
	return int(input())

def MAP():
	return map(int, input().split())

def MAP2():
	return map(float, input().split())

def LIST():
	return list(map(int, input().split()))

def STRING():
	return input()
import string
import sys
from heapq import heappop, heappush
from bisect import *
from collections import deque, Counter, defaultdict
from math import *
from itertools import permutations, accumulate
dx = [-1, 1, 0, 0]
dy = [0, 0, 1, -1]
(n, m) = MAP()
if m == 0:
	print(n, n)
	exit(0)
x = n // 2
if n % 2 != 0:
	x += 1
if m >= x:
	mn = 0
else:
	mn = n - 2 * m
i = n
while i * (i - 1) // 2 > m:
	i -= 1
rem = n - i
k1 = i * (i - 1) // 2
k2 = m - k1
mx = rem
if k2 > 0:
	mx -= 1
print(mn, mx)


(n, m) = map(int, input().split())
c = 1
r = m
while r > 0:
	d = min(c, r)
	r -= d
	c += 1
r = n
if c > 1:
	r = n - c
mi = max(0, n - 2 * m)
print(mi, r)


a = list(map(int, input().split()))
print('%d' % (lambda v, e: 0 if v <= 2 * e else v - 2 * e)(*a), end=' ')
if a[1] == 0:
	print(a[0])
else:
	ans = 0
	l = 1
	r = 100000
	while True:
		if l > r:
			break
		mid = (l + r) // 2
		if mid * mid - mid - (a[1] << 1) >= 0:
			ans = mid
			r = mid - 1
		else:
			l = mid + 1
	print(a[0] - ans)


(n, m) = [int(x) for x in input().split()]
if m == 0:
	mi = n
	ma = n
else:
	mi = max(0, n - 2 * m)
	nu = 0
	mu = 0
	while mu < m:
		if nu == 0:
			mu = 1
			nu = 2
		else:
			mu += nu
			nu += 1
	ma = n - nu
print(mi, ma)


(n, e) = map(int, input().split())
maxi = -1
for i in range(n + 1):
	if i * (i - 1) / 2 < e:
		maxi = i
print(max(0, n - 2 * e), n - (maxi + 1), sep=' ')


from sys import stdin, stdout
from collections import Counter

def ai():
	return list(map(int, input().split()))

def ei():
	return map(int, input().split())

def ip():
	return int(stdin.readline())

def op(ans):
	return stdout.write(str(ans) + '\n')
(n, m) = ei()
min = max(0, n - 2 * m)
k = 0
while k * (k - 1) < 2 * m:
	k += 1
print(min, n - k)


(n, m) = [int(i) for i in input().split()]
a = n - 2 * m
if m == 0:
	print(n, n)
else:
	if a < 0:
		a = 0
	b = (1 + 8 * m) ** 0.5
	b = b + 1
	c = b / 2
	if c != b // 2:
		c = c + 1
	b = n - int(c)
	print(a, b)


(n, m) = map(int, input().split())
a1 = max(0, n - 2 * m)
k = 0
while k * (k - 1) < 2 * m:
	k += 1
print(a1, n - k)


(n, m) = map(int, input().split())
minv = n - m * 2
if minv < 0:
	minv = 0
for i in range(n + 1):
	if i * (i - 1) // 2 >= m:
		break
maxv = n - i
print(minv, maxv)


(n, m) = map(int, input().split())
imin = max(0, n - 2 * m)
s = 0
k = 1
while s < m:
	s = k * (k - 1) // 2
	k += 1
print(imin, n - k + 1)


(n, m) = map(int, input().split())
current = 1
remaining = m
while remaining > 0:
	d = min(current, remaining)
	remaining -= d
	current += 1
result = n
if current > 1:
	result = n - current
print(max(0, n - m * 2), ' ', result)


(n, m) = map(int, input().split())
cliq = 1
rem = m
while rem > 0:
	rem -= min(rem, cliq)
	cliq += 1
ans = n
if cliq > 1:
	ans = n - cliq
print(max(0, n - 2 * m), ans)


(n, m) = list(map(int, input().split()))
ans1 = max(0, n - m * 2)
if m == 0:
	print(n, n)
	exit()
for i in range(n + 2):
	if i * (i - 1) // 2 > m:
		break
ans2 = n - i - (1 if (i - 1) * (i - 2) // 2 < m else 0) + 1
print(ans1, ans2)


def fun():
	lst = [int(x) for x in input().split()]
	if lst[0] == 1:
		print(1, 1)
		return
	if lst[1] == 0:
		print(lst[0], lst[0])
		return
	nmin = 0
	nmax = 0
	if lst[0] > lst[1] * 2:
		nmin = lst[0] - lst[1] * 2
	n = 2
	for i in range(2, lst[0]):
		if (i - 1) * i // 2 <= lst[1]:
			n = i
		else:
			break
	if (n - 1) * n // 2 == lst[1]:
		nmax = lst[0] - n
	else:
		nmax = lst[0] - n - 1
	print(nmin, nmax)
fun()


def solve(n, m):
	if n == 1 or m == 0:
		return (n, n)
	min_iso = 0 if m > n / 2 else n - m * 2
	edges = 0
	for cur_n in range(2, n + 1):
		edges += cur_n - 1
		if m <= edges:
			break
	max_iso = n - cur_n
	return (min_iso, max_iso)
(n, m) = map(int, input().split())
print(' '.join(map(str, solve(n, m))))


(n, m) = map(int, input().split())
for i in range(n + 1):
	if i * (i - 1) // 2 >= m:
		maax = n - i
		break
miin = max(n - 2 * m, 0)
if m == 0:
	miin = n
print(f'%d %d' % (miin, maax))


(n, m) = map(int, input().split())
if (n + 1) // 2 <= m:
	print(0, end=' ')
else:
	print(n - m * 2, end=' ')
k = 0
while k < n:
	if k * (k - 1) // 2 < m:
		k += 1
		continue
	else:
		break
print(n - k)


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit()
mi = max(0, n - 2 * m)
rec = 0
for i in range(n, -1, -1):
	if m - i * (i - 1) // 2 >= 0:
		rec += i
		m -= i * (i - 1) // 2
		break
while m > 0:
	m -= rec
	rec += 1
print(mi, n - rec)


(n, m) = map(int, input().split())
min_res = max(0, n - 2 * m)
(l, r) = (min_res, n + 1)

def check(tmp):
	t = n - tmp
	return t * (t - 1) // 2 >= m
while l != r - 1:
	tmp = (l + r) // 2
	if check(tmp):
		l = tmp
	else:
		r = tmp
print(min_res, l)


(n, m) = map(int, input().split())
mini = max(0, n - 2 * m)
maxi = 10 ** 10
for i in range(n + 1):
	if i * (i - 1) // 2 < m:
		continue
	maxi = min(maxi, i)
print(mini, n - maxi)


(n, m) = list(map(int, input().split(' ')))
mn = max(0, n - 2 * m)
mx = 0
for i in range(1, n + 1):
	if m <= i * (i - 1) / 2:
		mx = n - i
		break
if m == 0:
	mn = mx = n
print(mn, mx)


import math, string, itertools, fractions, heapq, collections, re, array, bisect, sys, copy, functools
inf = 10 ** 20
eps = 1.0 / 10 ** 10
mod = 10 ** 9 + 7
mod2 = 998244353
dd = [(-1, 0), (0, 1), (1, 0), (0, -1)]
ddn = [(-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]

def LI():
	return list(map(int, sys.stdin.readline().split()))

def LLI():
	return [list(map(int, l.split())) for l in sys.stdin.readlines()]

def LI_():
	return [int(x) - 1 for x in sys.stdin.readline().split()]

def LF():
	return [float(x) for x in sys.stdin.readline().split()]

def LS():
	return sys.stdin.readline().split()

def I():
	return int(sys.stdin.readline())

def F():
	return float(sys.stdin.readline())

def S():
	return input()

def pf(s):
	return print(s, flush=True)

def pe(s):
	return print(str(s), file=sys.stderr)

def JA(a, sep):
	return sep.join(map(str, a))

def JAA(a, s, t):
	return s.join((t.join(map(str, b)) for b in a))

def IF(c, t, f):
	return t if c else f

def YES(c):
	return IF(c, 'YES', 'NO')

def Yes(c):
	return IF(c, 'Yes', 'No')

def main():
	t = 1
	rr = []
	for _ in range(t):
		(n, m) = LI()
		r1 = max(0, n - m * 2)
		r2 = r1
		if m > 0:
			for i in range(n):
				m -= i
				if m <= 0:
					r2 = n - i - 1
					break
		rr.append(JA([r1, r2], ' '))
	return JA(rr, '\n')
print(main())


from math import sqrt, ceil
(n, m) = map(int, input().split())
Min = n - 2 * m
Min = max(0, Min)
Max = int(n - ceil((1 + sqrt(1 + 8 * m)) / 2))
Max = max(0, Max)
if m == 0:
	Min = Max = n
print(Min, Max)


(n, m) = map(int, input().split())
min_ = max(n - 2 * m, 0)
for i in range(10 ** 6):
	if i * (i - 1) // 2 >= m:
		max_ = n - i
		break
print(min_, max_)


import math as ma
import sys
from sys import exit
from decimal import Decimal as dec
from itertools import permutations

def li():
	return list(map(int, input().split()))

def modInverse(a, m):
	m0 = m
	y = 0
	x = 1
	if m == 1:
		return 0
	while a > 1:
		q = a // m
		t = m
		m = a % m
		a = t
		t = y
		y = x - q * y
		x = t
	if x < 0:
		x = x + m0
	return x

def num():
	return map(int, input().split())

def nu():
	return int(input())

def find_gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x
(n, m) = num()
mx = 0
for i in range(1, n + 1):
	z = i * (i - 1) // 2
	if m > z:
		continue
	mx = n - i
	break
if m == 0:
	mx = n
mn = 0
if n % 2 == 0:
	if m <= n // 2:
		mn = (n // 2 - m) * 2
else:
	zp = n // 2
	if m <= zp:
		mn = (zp - m) * 2 + 1
if m == 0:
	mn = n
print(mn, mx)


(vert_num, edge_num) = list(map(int, input().strip().split()))
if edge_num == 0:
	print(vert_num, vert_num)
else:
	max_isolated_verts = 0
	min_isolated_verts = max(0, vert_num - edge_num * 2)
	vertexes = 0
	max_edges = 0
	for v in range(1, vert_num + 1):
		max_edges += v - 1
		if max_edges >= edge_num:
			max_isolated_verts = max(0, vert_num - v)
			break
	print(min_isolated_verts, max_isolated_verts)


(n, m) = map(int, input().split())
if m == 0:
	ans1 = ans2 = n
else:
	ans1 = max(0, n - 2 * m)
	i = 1
	while m > 0:
		m -= i
		i += 1
	ans2 = n - i
print(ans1, ans2)


(n, m) = map(int, input().split())
minn = n - min(m * 2, n)
dp = [0 for i in range(100007)]
dp[1] = 1
q = 0
if m == 0:
	print(n, n)
	exit(0)
if 1 >= m:
	q = 2
else:
	for i in range(2, len(dp)):
		dp[i] = dp[i - 1] + i
		if dp[i] >= m:
			q = i + 1
			break
maxx = n - q
print(minn, maxx)


import math
(n, m) = list(map(int, input().strip().split()))
if m == 0:
	print(n, n)
else:
	a = max(n - 2 * m, 0)
	b = math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
	print(a, n - b)


(n, m) = map(int, input().split())
(a, b) = (1, m)
ans = n
while b > 0:
	b -= min(a, b)
	a += 1
if a > 1:
	ans = n - a
print(max(0, n - m * 2), ans)


def binarySearch(start, end, goal):
	if start > end:
		return end
	midPoint = (start + end) // 2
	needed = (midPoint - 1) * midPoint // 2
	if needed <= goal:
		return binarySearch(midPoint + 1, end, goal)
	else:
		return binarySearch(start, midPoint - 1, goal)

def solve(vertex, edge):
	minimum = 0
	maximum = 0
	currVertex = 1
	if edge == 0:
		print(vertex, vertex)
		return
	if edge * 2 < vertex:
		minimum = vertex - edge * 2
	ans = binarySearch(1, vertex, edge)
	remainEdge = edge - (ans - 1) * ans // 2
	if remainEdge > 0:
		ans += 1
	maximum = vertex - ans
	print(minimum, maximum)
(v, e) = list(map(int, input().split()))
solve(v, e)


(n, m) = [int(x) for x in input().split(' ')]
mini = max(0, n - 2 * m)
maxi = 0
for i in range(1, n + 1):
	if m <= i * (i - 1) / 2:
		maxi = n - i
		break
if m == 0:
	mini = maxi = n
print(mini, maxi)


(n, m) = map(int, input().split())
res = 0
check = 0
for i in range(n + 1):
	if i ** 2 - i - 2 * m >= 0 and check == 0:
		res = i
		check = 1
print(max(n - 2 * m, 0), max(n - res, 0))


(n, m) = map(int, input().split())
ans1 = max(0, n - 2 * m)
r = 0
a = 1
t = 0
for i in range(2, 111111):
	r += a
	a += 1
	if r >= m:
		t = i
		break
if m == 0:
	ans2 = n
elif m == 1:
	ans2 = n - 2
else:
	ans2 = max(0, n - t)
print(ans1, ans2)


(n, m) = map(int, input().split())
ans_min_ver = max(n - 2 * m, 0)
ans_max_ver = 1
need_add_links = m
while need_add_links > 0:
	add = min(ans_max_ver, need_add_links)
	need_add_links -= add
	ans_max_ver += 1
if ans_max_ver > 1:
	ans_max_ver = n - ans_max_ver
else:
	ans_max_ver = n
print(*(ans_min_ver, ans_max_ver))


import sys
import bisect as bi
import collections as cc
N = 2 * 10 ** 5 + 5
i = 1
ar = []
while i * i <= N:
	ar.append([i, i * i])
	i += 1
import sys
import collections as cc
input = sys.stdin.readline
I = lambda : list(map(int, input().split()))
ar = [i * (i - 1) // 2 for i in range(1, 1000)]
(n, m) = I()
mi = max(0, n - 2 * m)
tot = m
ini = 1
while tot:
	now = min(ini, tot)
	tot -= now
	ini += 1
mx = n
if ini - 1:
	mx = n - ini
print(mi, mx)


(n, m) = map(int, input().split())

def calc_edges(n):
	return n * (n - 1) // 2

def bin_search(low, high, m):
	while low <= high:
		mid = (low + high) // 2
		f_res = calc_edges(mid)
		if f_res == m:
			return mid
		elif f_res < m:
			low = mid + 1
		else:
			high = mid - 1
	return mid if f_res <= m else mid - 1

def solve(n, m):
	if m == 0:
		return (n, n)
	num_nodes = bin_search(0, n, m)
	if calc_edges(num_nodes) < m:
		mx = n - (num_nodes + 1)
	else:
		mx = n - num_nodes
	if 2 * m >= n:
		mn = 0
	else:
		mn = n - 2 * m
	return (mn, mx)
print(*solve(n, m))


(n, m) = tuple(map(int, input().split()))
minn = max(n - m * 2, 0)
for maxn in range(0, n + 1):
	if maxn * (maxn - 1) / 2 >= m:
		break
print('{} {}'.format(minn, n - maxn))


l = list(map(int, input().split()))
a = l[0]
b = l[1]
if b == 0:
	print(a, a)
	exit(0)
Min = max(0, a - b * 2)
Max = 0
i = 1
while Max < b:
	Max += i
	i += 1
Max = max(0, a - i)
print(Min, Max)


(n, m) = map(int, input().split())
minn = n - 2 * m
if minn <= 0:
	minn = 0
arr = []
arr.append(0)
for i in range(1, n + 1):
	x = i * (i - 1) // 2
	arr.append(x)
d = 0
for i in range(len(arr)):
	if m <= arr[i]:
		d = i
		break
if m == 0:
	print(n, n)
else:
	print(minn, n - d)


(n, m) = map(int, input().split())
mn = max(0, n - 2 * m)
if m == 0:
	mx = n
else:
	v = 2
	edges = 1
	while v < n and edges < m:
		edges += min(m - edges, v)
		v += 1
	mx = n - v
print(mn, mx)


import math
(a, b) = list(map(int, input().split()))
ans = a - b * 2
if ans <= 0:
	ans1 = 0
else:
	ans1 = ans
if b == 0:
	ans2 = a
else:
	k = math.ceil((-1 + (1 + 8 * b) ** 0.5) / 2) + 1
	if a - k <= 0:
		ans2 = 0
	else:
		ans2 = a - k
print(ans1, ans2)


(n, m) = [int(i) for i in input().split()]
maxnodes = 0
maxedges = 0
while maxedges < m:
	maxedges += maxnodes
	maxnodes += 1
mx = n - maxnodes
mn = max(n - 2 * m, 0)
print(mn, mx)


(n, m) = map(int, input().split(' '))
if n == 1 or m == 0:
	print(n, n)
else:
	mi = max(0, n - m * 2)
	ma = max(0, n - m - 1)
	k = (1 + (1 + 8 * m) ** 0.5) // 2 + int((1 + (1 + 8 * m) ** 0.5) % 2 > 0)
	print(mi, n - int(k))


import sys, math
from collections import defaultdict
MOD = 1000000007

def get_array():
	return list(map(int, sys.stdin.readline().split()))

def get_ints():
	return map(int, sys.stdin.readline().split())

def input():
	return sys.stdin.readline()

def print_array(a):
	print(' '.join(map(str, a)))

def main():
	(n, m) = get_ints()
	x = max(0, n - 2 * m)
	i = [0]
	for j in range(1, 100001):
		i.append(j + i[j - 1])
	y = 0
	while y < n + 1 and m > i[y]:
		y += 1
	y = -1 if m == 0 else y
	print(x, n - y - 1)
main()


import sys, os
from math import sqrt, gcd, ceil, log, floor, sin, pi
from math import factorial as fact
from bisect import bisect, bisect_left
from collections import defaultdict, Counter, deque
from heapq import heapify, heappush, heappop
from itertools import permutations
input = sys.stdin.readline
read = lambda : list(map(int, input().strip().split()))
MOD = 10 ** 9 + 7

def f(n):
	m = max(0, int(sqrt(2 * n)) - 10)
	for i in range(m, m + 20):
		if i * (i - 1) // 2 >= n:
			return i

def main():
	(n, m) = read()
	print(max(0, n - 2 * m), max(0, n - f(m)))
main()


import math
(n, m) = map(int, input().split(' '))
if n <= 2 * m:
	minimum = 0
else:
	minimum = n - 2 * m
if m == 0:
	maximum = n
else:
	maximum = int(n - (1 + math.sqrt(1 + 8 * m)) / 2)
print('{} {}'.format(minimum, maximum))


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit(0)
if m == 1:
	print(n - 2, n - 2)
	exit(0)
else:
	if n <= m * 2:
		m_min = 0
	else:
		m_min = n - m * 2
	z = 1
	zz = 1
	while True:
		z += 1
		zz = z * (z - 1) / 2
		if zz >= m:
			break
	print(m_min, n - z)


from math import ceil
(n, m) = map(int, input().split())
if m >= ceil(n / 2):
	print(0, end=' ')
else:
	print(n - 2 * m, end=' ')
if m == 0:
	print(n)
elif m == 1:
	print(n - 2)
else:
	i = 0
	while i * (i - 1) // 2 <= m:
		i += 1
	i -= 1
	if i * (i - 1) // 2 == m:
		print(n - i)
	else:
		print(n - i - 1)


(a, b) = list(map(int, input().split()))
k = 0
n = 1
while n <= b:
	n = n + k
	k = k + 1
max = a - k
min = a - 2 * b
if min < 0:
	min = 0
print(min, max)


from math import ceil as c
(a, b) = map(int, input().split())
print(max(0, a - 2 * b), end=' ')
lo = 0
hi = 100000
ans = 0
while lo <= hi:
	mid = (lo + hi) // 2
	if mid * (mid - 1) // 2 >= b:
		ans = mid
		hi = mid - 1
	else:
		lo = mid + 1
print(a - ans)


import math
s = input()
n = int(s.split(' ')[0])
m = int(s.split(' ')[1])
if m > n // 2:
	mini = 0
else:
	mini = n - m * 2
if m == 0:
	maxi = n
else:
	maxi = n - math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
print(mini, maxi)


(n, m) = list(map(int, input().split()))
ans1 = n - m * 2
ans2 = n
a = n * (n - 1) // 2
amount = n - 1
if m > 0:
	while a - amount >= m:
		a -= amount
		ans2 -= 1
		amount -= 1
	if n - m * 2 > 0:
		print(ans1, n - ans2)
	else:
		print(0, n - ans2)
else:
	print(n, n)


(n, m) = map(int, input().split())
i = 0
while (i * i - i) // 2 < m:
	i += 1
a = n - i
while m > 0 and n > 0:
	if n >= 2:
		n -= 2
	else:
		n -= 1
	m -= 1
print(n, a)


(n, m) = map(int, input().split())
if n - 2 * m <= 0:
	print(0, end=' ')
else:
	print(n - 2 * m, end=' ')
if m == 0:
	print(n, end=' ')
	exit()
for i in range(1, n + 1):
	k = i * (i - 1) // 2
	if k >= m:
		break
print(n - i, end=' ')


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit(0)
(mn, mx) = (-1, -1)
mn = max(0, n - m - m)
k = 1
while k * (k - 1) // 2 < m:
	k += 1
print(mn, n - k)


def calc(n, m):
	if m == 0:
		return 0
	i = 1
	while True:
		edge_cnt = i * (i - 1) // 2
		if edge_cnt >= m:
			return i
		i += 1
while True:
	try:
		(n, m) = map(int, input().split())
		Min = max(0, n - m * 2)
		if m == 0:
			Max = n
		else:
			Max = n - calc(n, m)
		print(Min, Max)
	except EOFError:
		break


(n, m) = map(int, input().split())
t = (n + 1) // 2
if t > m:
	a = n - 2 * m
else:
	a = 0
l = -1
r = n
while r - l > 1:
	q = (l + r) // 2
	if q * (q - 1) >= 2 * m:
		r = q
	else:
		l = q
print(a, n - r)


(n, m) = map(int, input().split())
if m == 0:
	mx = n
else:
	i = 2
	while i * (i - 1) / 2 < m:
		i += 1
	mx = n - i
if 2 * m >= n:
	mn = 0
else:
	mn = n - 2 * m
print(mn, mx)


nm = list(map(int, input().split()))
n = int(nm[0])
m = int(nm[1])
if m == 0:
	print(n, n)
if n <= 2 * m:
	f = 1
else:
	f = 2
for i in range(1, n + 1):
	if m <= int(i * (i - 1) / 2):
		break
if m != 0:
	if f == 1:
		print(0, n - i)
	if f == 2:
		print(n - 2 * m, n - i)


import sys
import os

def solve(n, m):
	if m == 0:
		return (n, n)
	minimum = max(0, n - m * 2)
	for i in range(1, n + 1):
		if i * (i - 1) // 2 >= m:
			return (minimum, n - i)

def main():
	(n, m) = (int(x) for x in input().split())
	print(' '.join((str(x) for x in solve(n, m))))

def __starting_point():
	main()
__starting_point()


import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	(mi, mx) = (0, 0)
	mi = max(0, n - 2 * m)
	left = 0
	right = int(1000000.0)
	while left < right:
		mid = (left + right) // 2
		if mid * (mid - 1) // 2 > m:
			right = mid
		else:
			left = mid + 1
	left -= 1
	if left * (left - 1) // 2 < m:
		left += 1
	mx = max(0, n - left)
	print(mi, mx)


from sys import stdin, stdout, setrecursionlimit
from gc import disable
from math import ceil
disable()
gets = input
puts = print
input = stdin.readline
print = stdout.write

def main() -> int:
	(n, m) = map(int, input().split())
	mmin = n - 1
	mmax = n * (n - 1) // 2
	_n = ceil((1 + (1 + 8 * m) ** 0.5) / 2)
	if m > n / 2:
		print('0 ')
	else:
		print('%i ' % (n - 2 * m))
	if not m:
		print('%i' % n)
	else:
		puts(n - _n)
	return 0
main()


(n, m) = [int(j) for j in input().split()]
k = 0
for i in range(10 ** 20):
	if i * (i - 1) // 2 >= m:
		k = i
		break
print(max(0, n - 2 * m), max(0, n - k))


(n, m) = map(int, input().split())
l = 0
r = n
for i in range(50):
	md = (l + r) // 2
	if md * (md - 1) // 2 < m:
		l = md
	else:
		r = md
print(max(0, n - m * 2), n - r)


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	imin = max(0, n - 2 * m)
	(l, r) = (-1, n + 1)
	while l + 1 < r:
		mid = (l + r) // 2
		if (n - mid) * (n - mid - 1) // 2 < m:
			r = mid
		else:
			l = mid
	print(imin, l)


USE_STDIO = False
if not USE_STDIO:
	try:
		import mypc
	except:
		pass

def main():
	(n, m) = map(int, input().split(' '))
	if m == 0:
		print(n, n)
		return
	minc = max(0, n - m * 2)
	x = int((m * 2) ** 0.5)
	if x * (x + 1) < m * 2:
		x += 1
	maxc = n - (x + 1)
	print(minc, maxc)
main()


(n, m) = map(int, input().split())
minIsolated = max(0, n - 2 * m)
cur = 1
remain = m
while remain > 0:
	d = min(cur, remain)
	remain -= d
	cur += 1
maxIsolated = n
if cur > 1:
	maxIsolated = n - cur
print(minIsolated, maxIsolated)


from math import ceil
(n, m) = map(int, input().split())
if m == 0:
	s = 0
elif m == 1:
	s = 2
else:
	(a, b) = (2, n)
	while b - a > 1:
		s = (a + b) // 2
		if s * (s - 1) // 2 < m:
			a = s
		else:
			b = s
	s = b
print(max(0, n - 2 * m), n - s)


(n, m) = [int(el) for el in input().split()]
mn = n - m * 2
if mn < 0:
	mn = 0
x = 0.5 + (2 * m + 0.25) ** 0.5
s = str(x)
q = len(s)
if s[q - 2:] == '.0':
	x = x - 1
mx = n - int(x) - 1
if m == 0:
	mx = n
if mx < 0:
	mx = 0
print(mn, mx)


(n, m) = map(int, input().split())
print(max(n - 2 * m, 0), n - next((i for i in range(n + 1) if i * (i - 1) // 2 >= m)))


def poisk(x, l, r):
	if l >= r - 1:
		return r
	y = (l + r) // 2
	if y * (y - 1) // 2 >= x:
		r = y
	else:
		l = y
	return poisk(x, l, r)
(n, m) = map(int, input().split())
k = n - m * 2
if k < 0:
	k = 0
print(k, n - poisk(m, -1, 10 ** 5))


[n, m] = [int(x) for x in input().split(' ')]
minimum = n - 2 * m
if minimum < 0:
	minimum = 0
maximum = 0
if m == 0:
	maximum = n
elif m == 1:
	maximum = n - 2
else:
	hran_k_vrcholovy_uplny = 1
	for vrcholov in range(2, n):
		if m <= hran_k_vrcholovy_uplny:
			maximum = n - vrcholov
			break
		else:
			hran_k_vrcholovy_uplny += vrcholov
output = [minimum, maximum]
print(' '.join((str(x) for x in output)))


def binarySearch(x, arr, l, r):
	mid = int((l + r) / 2)
	while l <= r:
		if arr[mid] < x:
			l = mid + 1
		elif arr[mid] == x:
			return mid
		elif arr[mid] >= x:
			r = mid - 1
		mid = int((l + r) / 2)
	return mid
(vert, edges) = [int(x) for x in input().split()]
if edges == 0:
	print(vert, vert)
	exit()
ed = int(vert / 2)
if edges > ed:
	print(0, end=' ')
else:
	print(vert - edges * 2, end=' ')
x = []
for i in range(2, vert + 1):
	x.append(int(i * (i - 1) / 2))
el = binarySearch(edges, x, 0, len(x) - 1)
if x[el] == edges:
	print(vert - el - 2)
elif edges == 1:
	print(vert - 2)
else:
	el += 3
	print(vert - el)


(v, e) = map(int, input().split())

def minv(v, e):
	if v - 2 * e < 0:
		return 0
	else:
		return v - 2 * e

def maxv(v, e):
	ans = 0
	if e == 0:
		return v
	for i in range(2, v):
		ans = ans + i - 1
		if ans >= e:
			return v - i
	return 0
print(minv(v, e), maxv(v, e))


f = lambda : map(int, input().split(' '))
(v, e) = f()
if e == 0:
	print(v, v)
else:
	mini = v - e * 2
	if mini < 0:
		mini = 0
	low = 0
	high = v
	a = []
	while low < high:
		mid = (low + high) // 2
		if mid in a:
			maxi = v - high
			break
		else:
			a.append(mid)
		if mid * (mid - 1) // 2 == e:
			maxi = v - mid
			break
		elif mid * (mid - 1) // 2 > e:
			high = mid
		else:
			low = mid
	print(mini, maxi)


from math import sqrt, ceil
(n, k) = map(int, input().split())
print(max(n - k * 2, 0), end=' ')
res = 0
for i in range(n + 1):
	if i * (i - 1) // 2 >= k:
		print(n - i)
		exit()


(n, m) = (int(i) for i in input().split())
if n == 1:
	print(1, 1)
else:
	minn = max(0, n - m * 2)
	maxx = n
	for i in range(min(n, 2 * m), 1, -1):
		if i * (i - 1) // 2 >= m:
			maxx = n - i
		else:
			break
	print(minn, maxx)


from sys import stdin
(n, m) = map(int, stdin.readline().split())
ans_min = n
ans_max = 0
for i in range(n + 1):
	k = n - i
	mx = k * (k - 1) // 2
	mn = k // 2 + k % 2
	if mn <= m <= mx:
		ans_min = min(ans_min, i)
		ans_max = max(ans_max, i)
print(ans_min, ans_max)


import math
(n, m) = list(map(int, input().split()))
mn = 0
if m > n // 2:
	mn = 0
else:
	mn = n - m * 2
if m == 0:
	mx = n
else:
	t = (1 + math.sqrt(1 + 8 * m)) / 2
	if t != int(t):
		t = int(t) + 1
	else:
		t = int(t)
	mx = max(n - t, 0)
print('{} {}'.format(mn, mx))


from math import *
(n, m) = list(map(int, input().split()))
if 2 * m >= n:
	minimum = 0
else:
	minimum = n - 2 * m
n1 = ceil((1 + sqrt(1 + 8 * m)) / 2)
if m == 0:
	print(n, n)
else:
	print(minimum, n - n1)


def f(n, m):
	mx = 0
	kp = m
	for i in range(1, n + 1):
		kp -= i
		if kp <= 0:
			return n - (i + 1)
(n, m) = map(int, input().split())
if m == 0:
	(mn, mx) = (n, n)
elif n > m:
	if n % 2 == 0 and m >= n / 2:
		mn = max(0, n - 2 * m)
		mx = f(n, m)
	elif n % 2 == 0 and m < n / 2:
		mn = max(0, n - 2 * m)
		mx = f(n, m)
	elif n % 2 != 0 and m <= n // m:
		mn = max(0, n - 2 * m)
		mx = f(n, m)
	elif n % 2 != 0 and m > n // m:
		mn = max(0, n - 2 * m)
		mx = f(n, m)
else:
	mn = 0
	mx = f(n, m)
print(mn, mx)


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	quit()
mi = n - 2 * m
if mi < 0:
	mi = 0
i = 0
for i in range(1, 10 ** 5 + 1):
	c = i * (i - 1) // 2
	if c >= m:
		break
print(mi, n - i)


def C(num):
	return num * (num - 1) // 2
(n, m) = map(int, input().split(' '))
lower = max(0, n - 2 * m)
if m == 0:
	print(str(n) + ' ' + str(n))
else:
	for i in range(1, n):
		if m > C(i) and m <= C(i + 1):
			upper = i + 1
			break
	print(str(lower) + ' ' + str(n - upper))


import sys, bisect
(n, m) = map(int, sys.stdin.readline().split())
left = max(n - 2 * m, 0)
if m == 0:
	print(left, n)
else:
	temp = []
	for i in range(2, n + 1):
		temp.append(i * (i - 1) // 2)
	temp.sort()
	idx = bisect.bisect_left(temp, m)
	print(left, n - (idx + 2))


import math
(n, m) = list(map(int, input().split()))
MINANS = max(0, n - m * 2)

def combi(m):
	return m * (m - 1) // 2
for i in range(int(math.sqrt(2 * m)), n + 1):
	if combi(i) >= m:
		break
MAXANS = n - i
print(MINANS, MAXANS)


(n, m) = map(int, input().split(' '))
minNodes = max(0, n - m * 2)
maxNodes = n
if m == 0:
	print(minNodes, maxNodes)
else:
	for i in range(1, n + 1):
		if m <= i:
			maxNodes = n - i - 1
			break
		m -= i
	print(minNodes, maxNodes)


(n, m) = [int(s) for s in input().split()]
(s, i) = (1, 0)
min = max(0, n - m * 2)
print(min, end=' ')
while s <= m:
	i += 1
	s += i
max = n - (i + 1)
if m == 0:
	print(n, end='')
else:
	print(max, end=' ')


import math
(n, m) = map(int, input().split())
_min = max(0, n - m * 2)
if m == 0:
	_max = n
else:
	nm = math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
	_max = min(n, n - nm)
print(_min, _max)


import math
(a, b) = map(int, input().split())
max_v = b + 1 if b == 1 else b * 2
for i in range(0, a + 1):
	if i * (i - 1) >= 2 * b:
		min_v = i
		break
print(0 if a - max_v <= 0 else a - max_v, a - min_v)


def line():
	return map(int, input().split())
from math import sqrt, ceil
(n, m) = line()
print(max(0, n - 2 * m), n if m == 0 else n - ceil((sqrt(m * 8 + 1) + 1) / 2))


import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	quit()
most = m * 2
least = math.ceil((1 + (1 + 8 * m) ** 0.5) / 2)
print(max(0, n - most), max(0, n - least))


from sys import stdin, stdout
from math import sin, tan, cos
(n, m) = map(int, stdin.readline().split())
if not m:
	stdout.write(str(n) + ' ' + str(n) + '\n')
else:
	stdout.write(str(max(0, n - 2 * m)) + ' ')
	(l, r) = (1, n + 1)
	while r - l > 1:
		mid = l + r >> 1
		if mid * (mid - 1) // 2 > m:
			r = mid
		else:
			l = mid
	ans = n - l
	if l * (l - 1) // 2 != m:
		ans -= 1
	stdout.write(str(ans))


from bisect import bisect_left
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
elif n == 1:
	print(1, 1)
else:
	mn = max(n - m * 2, 0)
	value = [int(n * (n - 1) / 2) for n in range(2, n + 5)]
	mx = bisect_left(value, m)
	mxm = max(n - mx - 2, 0)
	print(mn, mxm)


(v, r) = input().split()
v = int(v)
r = int(r)
if r == 0:
	min = v
	max = v
elif r >= v // 2 + v % 2 and r <= v:
	min = 0
elif r > v:
	min = 0
elif r < v // 2 + v % 2 and v % 2 == 1:
	min = (v // 2 + v % 2 - r) * 2 - 1
elif r < v // 2 + v % 2 and v % 2 == 0:
	min = (v // 2 + v % 2 - r) * 2
s = 0
y = 0
if r != 0:
	while s < r:
		y = y + 1
		s = s + y
	max = v - y - 1
print(min, max)


import os
import sys
(n, m) = [int(num) for num in sys.stdin.readline().split()]
res1 = max([0, n - 2 * m])
res2 = 0
while res2 * (res2 - 1) < 2 * m:
	res2 += 1
print(res1, n - res2)


(n, m) = map(int, input().split())
loli = max(0, n - 2 * m)
if m == 0:
	alfa = n
elif m >= 3:
	now = 1
	while m > 0:
		n -= 1
		m -= now
		now += 1
	alfa = max(0, n - 1)
else:
	alfa = max(0, n - (m + 1))
print(loli, alfa)


import math
import sys
DEBUG = False

def inp():
	return sys.stdin.readline().rstrip()

def dprint(*value, sep=' ', end='\n'):
	if DEBUG:
		print(*value, sep=sep, end=end)

def getpf(E):
	if E == 0:
		return 0
	e = 0
	for k in range(2, E + 100):
		e += k - 1
		if e >= E:
			return k
	assert False

def solve(V, E):
	mx = V - getpf(E)
	mn = max(0, V - E * 2)
	return (mn, mx)

def main():
	(N, M) = [int(e) for e in inp().split()]
	print(*solve(N, M))
main()


(n, m) = map(int, input().strip().split())
mn = 0
if n - m * 2 <= 0:
	mn = 0
else:
	mn = n - m * 2
c = 1
k = 0
while c <= m:
	c += k
	k += 1
mx = n - k
print(mn, mx)


import bisect
(x, y) = map(int, input().split())
lol = [0]
if x == 1:
	print(1, 1)
else:
	for i in range(1, x + 1):
		if i > 3:
			lol.append(i - 1 + (i - 2) * (i - 1) // 2)
		else:
			lol.append(i)
	if x - 2 * y <= 0:
		print(0, end=' ')
	else:
		print(x - 2 * y, end=' ')
	a = bisect.bisect(lol, y)
	if y == 1:
		if x - 1 >= 0:
			print(x - 2)
	elif y == 2 or y == 3:
		if x - 3 >= 0:
			print(x - 3)
	elif x - a >= 0:
		if lol[a - 1] == y:
			print(x - (a - 1))
		else:
			print(x - a)
	else:
		print(0)


import math
(a, b) = [int(i) for i in input().split()]
x = a - b * 2
if x <= 0:
	print(0, end=' ')
else:
	print(x, end=' ')
if b == 0:
	print(a, end=' ')
else:
	rs = math.ceil((-1 + math.sqrt(1 + 8 * b)) / 2) + 1
	x = a - rs
	if x <= 0:
		print(0, end=' ')
	else:
		print(x, end=' ')


import math
(v, e) = map(int, input().split())
root = (1 + math.sqrt(1 + 8 * e)) / 2
maxm = math.ceil(root)
maxm = maxm if e > 0 else maxm - 1
minm = v - 2 * e if e < math.ceil(v / 2) else 0
print(minm, v - maxm)


(n, m) = map(int, input().split())
iso_min = max(n - 2 * m, 0)
for i in range(n + 1):
	if m <= i * (i - 1) // 2:
		iso_max = n - i
		break
print(iso_min, iso_max)


for _ in range(1):
	(n, m) = map(int, input().split())
	a = 0
	if m * 2 >= n:
		a = 0
	else:
		a = n - 2 * m
	d = 0
	for i in range(0, n + 1):
		if m <= i * (i - 1) // 2:
			d = i
			break
	print(a, n - d)


def binarySearch(arr, l, r, x):
	ans = -1
	while l <= r:
		mid = l + (r - l) // 2
		if arr[mid] >= x:
			r = mid - 1
			ans = mid
		elif arr[mid] < x:
			l = mid + 1
		else:
			r = mid - 1
	return ans
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
else:
	if n - 2 * m < 0:
		print(0, end=' ')
	else:
		print(n - 2 * m, end=' ')
	a = [0]
	for i in range(1, 10 ** 5 + 1):
		a.append(a[-1] + i)
	z = binarySearch(a, 0, len(a) - 1, m)
	print(n - z - 1)


import math
import fractions
(n, m) = list(map(int, input().split()))
if m == 0:
	print(n, n)
	exit()
print(n - min(n, m * 2))
if m == 1:
	print(n - 2)
if m == 2:
	print(n - 3)
if m > 2:
	x = math.ceil(math.sqrt(m * 2 + fractions.Fraction(1, 4)) - fractions.Fraction(1, 2)) + 1
	print(n - x)


import math
(n, m) = input().split(' ')
n = int(n)
m = int(m)
print(max(0, n - 2 * m), end=' ')
d = math.ceil(math.sqrt(1 + 8 * m))
ans = math.ceil((1 + d) / 2)
if m == 0:
	print(n)
else:
	print(max(0, n - ans))


import math
values = list(map(int, input().split(sep=' ')))
n = values[0]
m = values[1]

def count(n, m):
	if m == 0:
		print(str(int(n)) + ' ' + str(int(n)))
		return
	if n == 1:
		maximum = 0
		minimum = 0
		print(str(int(minimum)) + ' ' + str(int(maximum)))
		return
	else:
		if int((1 + math.sqrt(1 + 8 * m)) / 2) == (1 + math.sqrt(1 + 8 * m)) / 2:
			maximum = n - int((1 + math.sqrt(1 + 8 * m)) / 2)
		else:
			maximum = n - int((1 + math.sqrt(1 + 8 * m)) / 2) - 1
		minimum = max(n - 2 * m, 0)
		print(str(int(minimum)) + ' ' + str(int(maximum)))
		return
count(n, m)


from math import sqrt, ceil
(n, m) = map(int, input().split())
k = 0
while m > k * (k - 1) // 2:
	k += 1
a = max(0, n - 2 * m)
b = n - k
print(a, b)


N = 100000.0 + 5
(n, m) = map(int, input().split(' '))
minn = max(0, n - m * 2)
mind = N
for i in range(0, int(N)):
	if i * (i - 1) / 2 >= m:
		mind = i
		break
maxx = max(0, n - mind)
print('%d %d' % (minn, maxx))


(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit()
ans = n - 2 * m
print(max(ans, 0), end=' ')
c = 2
while c * (c - 1) // 2 < m:
	c += 1
print(n - c)


import math
(n, m) = [int(x) for x in input().split()]
edges = (1 + math.sqrt(1 + 8 * m)) / 2
edges = math.ceil(edges)
maximum = n - edges
minimum = n - 2 * m
if minimum < 0:
	minimum = 0
if maximum < minimum:
	maximum = minimum
print(minimum, maximum)


import math
inp = input().split(' ')
n = int(inp[0])
m = int(inp[1])
x = n - m * 2
ans1 = 0
if x > 0:
	ans1 = x
ans2 = int(n - (1 + math.sqrt(1 + 8 * m)) / 2)
if m == 0:
	ans2 = n
print(str(ans1) + ' ' + str(ans2))


import math
(v, e) = map(int, input().split())
maxi = max(0, v - (e + 1))
mini = v - e * 2
for i in range(1, v + 1):
	d = i ** 2 - i
	if d >= 2 * e:
		fee = i
		break
if e == 0:
	print(v, v)
else:
	print(max(0, mini), min(v - 1, v - fee))


from math import ceil
(n, m) = [int(x) for x in input().split()]
mini = n - m * 2
for i in range(100001):
	z = i * (i - 1) / 2
	if z >= m:
		maxi = n - i
		break
if mini < 0:
	mini = 0
print(mini, maxi)


import math
import random
import sys
import collections

def In():
	return map(int, sys.stdin.readline().split())
input = sys.stdin.readline

def isoedge():
	(v, e) = In()
	pos = -1
	while True:
		if pos * (pos + 1) // 2 >= e:
			maxiso = v - pos - 1
			break
		pos += 1
	print(max(v - 2 * e, 0), maxiso)
isoedge()


import math
[n, m] = map(int, input().split())

def solve_function(a, b, c):
	d = b * b - 4 * a * c
	ans = []
	if d == 0:
		ret = 1
		ans = [ret, -b / 2 * a]
	elif d < 0:
		ret = 0
		ans = [ret]
	else:
		ret = 2
		ans = [ret, (-b + math.sqrt(d)) / 2 * a, (-b - math.sqrt(d)) / 2 * a]
	return ans
RetList = solve_function(1, -1, -2 * m)

def searchMaxConnectedNode(l, r):
	ret = l
	while ret * (ret - 1) // 2 < m:
		ret += 1
	return ret
maxConnectedNode = searchMaxConnectedNode(0, n)
minConnectedNode = m * 2
print(max(0, n - minConnectedNode), min(n, n - maxConnectedNode))


from math import sqrt, ceil
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
elif m == 1:
	print(n - 2, n - 2)
else:
	if n <= m * 2:
		mmin = 0
	else:
		mmin = n - m * 2
	x = 1
	edges = 1
	while True:
		x += 1
		edges = x * (x - 1) / 2
		if edges >= m:
			break
	print(mmin, n - x)


import sys

def rint():
	return map(int, sys.stdin.readline().split())
(n, m) = rint()
min_ans = max(0, n - 2 * m)
max_ans = 0
for i in range(0, n + 1):
	if m <= i * (i - 1) // 2:
		max_ans = max(0, n - i)
		break
print(min_ans, max_ans)


import math, sys, bisect, heapq
from collections import defaultdict, Counter, deque
from itertools import groupby, accumulate
int1 = lambda x: int(x) - 1
ilele = lambda : map(int, input().split())
alele = lambda : list(map(int, input().split()))
ilelec = lambda : map(int1, input().split())
alelec = lambda : list(map(int1, input().split()))

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def Y(c):
	print(['NO', 'YES'][c])

def y(c):
	print(['no', 'yes'][c])

def Yy(c):
	print(['No', 'Yes'][c])
(n, m) = ilele()
if n == 1:
	print(1, 1)
elif m == 0:
	print(n, n)
elif n == 2:
	print(0, 0)
else:
	req = math.ceil(n / 2)
	if m >= req:
		mini = 0
	else:
		mini = max(0, n - 2 * m)
	maxi = 0
	for i in range(1, n + 1):
		x = i * (i - 1) // 2
		if x >= m:
			maxi = n - i
			break
	print(mini, maxi)


def f(n, m):
	mn = max(n - m * 2, 0)
	mx = 0
	z = 0
	while z * (z - 1) // 2 < m:
		z += 1
	return (mn, max(n - z, 0))
(n, m) = map(int, input().strip().split())
print(*f(n, m))


(n, m) = map(int, input().split())
if n - m * 2 > 0:
	a1 = n - m * 2
else:
	a1 = 0
if m == 0:
	a2 = n
else:
	a2 = int(n - (1 + (1 + 8 * m) ** (1 / 2)) / 2)
print(a1, a2)


(n, m) = [int(s) for s in input().split(' ')]
min_iso = max(n - m * 2, 0)
a = 0
if m >= 1:
	while a * (a - 1) / 2 < m and a < n:
		a += 1
max_iso = n - a
print(min_iso, max_iso)


from math import sqrt
(n, m) = map(int, input().split())
mini = max(n - 2 * m, 0)
dn = 0.5 + 0.5 * sqrt(1 + 8 * m)
idn = int(dn)
mm = (2 * idn - 1) ** 2
maxi = idn + (mm != 8 * m + 1)
if m is 1 or m == 2:
	maxi = m + 1
maxi = n - maxi
if m is 0:
	maxi = n
print(mini, maxi)


from math import factorial as f

def readint():
	return int(input())

def readline():
	return [int(c) for c in input().split()]

def ncr2(n):
	return n * (n - 1) // 2

def main():
	(N, M) = readline()
	if N == 1:
		print('1 1')
		return
	i = N
	edges = M
	while i - 2 >= 0 and edges > 0:
		i -= 2
		edges -= 1
	if i == 1 and edges > 0:
		_min = 0
	else:
		_min = i
	nodes = 0
	rem = 1
	_max_nodes = 3
	for i in range(2, N):
		if i > N:
			break
		edges = i * (i - 1) // 2
		if edges < M:
			_max_nodes = i
		elif edges == M:
			_max_nodes = i
			rem = 0
		else:
			break
	_max = N - _max_nodes - rem
	_max = max(_min, _max)
	print(str(_min) + ' ' + str(_max))
main()


import math
(n, m) = map(int, input().split())
mini = max(0, n - 2 * m)
temp = 1
count = 1
while temp < m:
	count += 1
	temp += count
if m == 0:
	print(mini, n)
else:
	print(mini, n - count - 1)


from math import *
(n, m) = map(int, input().split())
minval = 0
maxval = 0
if m * 2 >= n:
	minval = 0
else:
	minval = n - m * 2
if m > 0:
	maxval = n - ceil((1 + sqrt(1 + 8 * m)) / 2)
else:
	maxval = n
print(minval, maxval)


import math

def most_edge(n):
	return n * (n - 1) // 2

def can(n, m):
	return most_edge(n) >= m
(n, m) = [int(x) for x in input().split()]
minn = n - 2 * m
minn = max(0, minn)
np = max(0, int(math.sqrt(2 * m)) - 10)
for i in range(np, np + 20):
	if not can(i, m):
		continue
	else:
		maxx = i
		break
maxx = n - maxx
print(minn, maxx)


(n, m) = list(map(int, input().split()))
how = 1
for i in range(1, n + 1):
	tmp = int(i * (i - 1) / 2)
	if tmp >= m:
		how = n - i
		break
if m == 0:
	how = n
if n == m and n == 1:
	ans1 = 0
else:
	ans1 = max(0, n - 2 * m)
print(ans1, how)


x = input().split(' ')
n = int(x[0])
m = int(x[1])
if m == 0:
	print(n, n)
else:
	i = 1
	ans = n
	while i <= n:
		if int(i * (i - 1) / 2) >= m:
			ans = i
			break
		i = i + 1
	print(max(0, n - 2 * m), n - ans)


(n, m) = (int(x) for x in input().split())
k = 0
while k * (k - 1) // 2 < m:
	k += 1
print(max(0, n - 2 * m), n - k)


(n, m) = [int(i) for i in input().split()]
x = 0
while x * (x + 1) // 2 < m:
	x += 1
if m == 0:
	print(n, n)
else:
	print(max(0, n - 2 * m), max(0, n - 1 - x))


import math
(n, m) = map(int, input().split(' '))
if m == 0:
	print(n, end=' ')
else:
	print(n - m * 2 if n - m * 2 > 0 else 0, end=' ')
if n == 1:
	print(1)
elif m == 0:
	print(n)
else:
	vert_used = math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
	print(n - vert_used if n - vert_used > 0 else 0)


import sys
inf = float('inf')
sys.setrecursionlimit(1000000)
from math import ceil, floor, log, sqrt, factorial, pow, pi, gcd
abc = 'abcdefghijklmnopqrstuvwxyz'
abd = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}
(mod, MOD) = (1000000007, 998244353)
vow = ['a', 'e', 'i', 'o', 'u']
(dx, dy) = ([-1, 1, 0, 0], [0, 0, 1, -1])

def get_array():
	return list(map(int, sys.stdin.readline().strip().split()))

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def input():
	return sys.stdin.readline().strip()
(n, m) = get_ints()
if m == 0:
	print(n, n)
	exit()
if m >= n * (n - 1) // 2:
	print(0, 0)
	exit()
d = 1 + 8 * m
min_vertex_covered = ceil((1 + sqrt(d)) / 2)
maxi = n - min_vertex_covered
maxi_vertex_covered = 2 * m
mini = max(0, n - maxi_vertex_covered)
print(mini, maxi)


import math
(n, m) = map(int, input().split())
x = 0
for i in range(2, n + 1):
	if i * (i - 1) < 2 * m:
		x = i + 1
	elif i * (i - 1) == 2 * m:
		x = i
	else:
		break
print(max(0, n - m * 2), n - x)


(n, m) = list(map(int, input().split()))
minn = max(0, n - 2 * m)
cur = 1
rem = m
while rem > 0:
	d = min(cur, rem)
	rem -= d
	cur += 1
res = n
if cur > 1:
	res = n - cur
print(' '.join([str(minn), str(res)]))


(n, m) = map(int, input().split())
if n > 1 and m >= n / 2:
	ans1 = 0
elif n > 1:
	ans1 = n - m * 2
else:
	ans1 = 1
k = 1
while k * (k - 1) // 2 < m:
	k += 1
if m > 0:
	ans2 = n - k
else:
	ans2 = n
print(ans1, ans2)


import math
(n, m) = map(int, input().split())
p = max(n - m * 2, 0)
r = math.sqrt(1 + 8 * m)
q = math.ceil((1 + r) / 2)
if m > 0:
	print(p, n - q)
else:
	print(n, n)


def poisk(x, l, r):
	if l >= r - 1:
		return r
	y = (l + r) // 2
	if y * (y - 1) // 2 >= x:
		r = y
	else:
		l = y
	return poisk(x, l, r)
(n, m) = map(int, input().split())
min1 = n - m * 2
if min1 < 0:
	min1 = 0
print(min1, n - poisk(m, -1, 1000000))


import math
(n, m) = map(int, input().split())
print(max(0, n - 2 * m), n - math.ceil((1 + (1 + 8 * m) ** 0.5) / 2) * (m != 0))


x = [int(i) for i in input().split()]
l = 0
if x[0] - 1 < x[1]:
	min = 0
else:
	min = x[0] - x[1] * 2
	if min < 0:
		min = 0
if x[1] == 0:
	max = x[0]
else:
	for i in range(x[0]):
		l += i
		if l == x[1]:
			max = x[0] - (i + 1)
			break
		elif l > x[1]:
			max = x[0] - (i + 1)
			break
print(min, max)


from sys import stdin, stdout
from math import gcd, sqrt
from collections import deque
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\n')
L = lambda : list(R())
P = lambda x: stdout.write(x)
hg = lambda x, y: (y + x - 1) // x * x
pw = lambda x: 1 if x == 1 else 1 + pw(x // 2)
chk = lambda x: chk(x // 2) if not x % 2 else True if x == 1 else False
N = 2 * 10 ** 5 + 1
(n, m) = R()
k = 0
while k * (k - 1) < 2 * m:
	k += 1
print(max(n - 2 * m, 0), n - k)


(n, k) = map(int, input().split())
mi = n // 2
ans_min = max(n - 2 * k, 0)
ans_max = 0
for i in range(1, n + 1):
	tmp = i * (i - 1) / 2
	if k <= tmp:
		ans_max = max(n - i, 0)
		break
if k == 0:
	ans_max = n
print(ans_min, ans_max)


import math
(n, m) = map(int, input().split())
(men, mex) = (0, 0)
if m == 0:
	l = 0
else:
	l = math.ceil((1 + math.sqrt(1 + 8 * m)) / 2)
mex = max(n - l, 0)
men = max(n - 2 * m, 0)
print(men)
print(mex)


(n, m) = map(int, input().split())
r = n - 2 * m
x = 0
while x * (x - 1) // 2 < m:
	x += 1
print(max(0, r), n - x)


(n, m) = map(int, input().strip().split())
miin = max(0, n - 2 * m)
if n == 1:
	miin = 1
ans = 0
z = 0
for i in range(0, n + 1):
	if m <= i * (i - 1) // 2:
		z = i
		break
print(str(miin) + ' ' + str(n - z))


(n, m) = list(map(int, input().split()))
min_isolated = 0
if n - m * 2 > 0:
	min_isolated = n - m * 2
for i in range(0, n + 1):
	if i * (i - 1) / 2 >= m:
		print(min_isolated, n - i)
		break


from math import sqrt, ceil
(n, m) = map(int, input().split())
if m >= 3:
	print(max(0, n - 2 * m), n - ceil((1 + sqrt(1 + 8 * m)) / 2))
elif m == 0:
	print(n, n)
elif m == 1:
	print(max(0, n - 2), max(0, n - 2))
elif m == 2:
	print(max(0, n - 4), max(0, n - 3))


(n, m) = list(map(int, input().split()))
x = 0
while True:
	if x * (x - 1) >> 1 >= m:
		break
	x += 1
print(max(n - (m << 1), 0), max(n - x, 0))


from math import sqrt, ceil
(n, k) = map(int, input().split())
print(max(n - k * 2, 0), end=' ')
a = (1 + ceil(sqrt(1 + 8 * k))) / 2
b = (1 - ceil(sqrt(1 + 8 * k))) / 2
if b >= 0:
	a = b
print(n - ceil(a))


def poisk(x, l, r):
	if l >= r - 1:
		return r
	y = (l + r) // 2
	if y * (y - 1) // 2 >= x:
		r = y
	else:
		l = y
	return poisk(x, l, r)
(n, m) = map(int, input().split())
min1 = n - m * 2
if min1 < 0:
	min1 = 0
max1 = n - poisk(m, -1, 10 ** 6)
print(min1, max1)


a = input()
n = 0
b = a.split()
q = int(b[0])
w = int(b[1])
if w * 2 >= q:
	t = 0
else:
	t = q - w * 2
while (n * n - n) / 2 < w:
	n = n + 1
h = q - n
print(t, h)


def solution(n, m):
	if m == 0:
		print('%d %d' % (n, n))
		return
	if n == 1:
		print('%d %d' % (1, 1))
		return
	minn = max(0, n - 2 * m)
	nodes = 1
	while (nodes - 1) * nodes / 2 < m:
		nodes += 1
	maxx = max(0, n - nodes)
	print('%d %d' % (minn, maxx))
(n, m) = [int(val) for val in input().split()]
solution(n, m)


class CodeforcesTask1065BSolution:

	def __init__(self):
		self.result = ''
		self.n_m = []

	def read_input(self):
		self.n_m = [int(x) for x in input().split(' ')]

	def process_task(self):
		mn = max(self.n_m[0] - self.n_m[1] * 2, 0)
		x = 1
		while x * (x - 1) // 2 < self.n_m[1]:
			x += 1
		mx = self.n_m[0] - x
		self.result = '{0} {1}'.format(mn, max(mn, mx))

	def get_result(self):
		return self.result
Solution = CodeforcesTask1065BSolution()
Solution.read_input()
Solution.process_task()
print(Solution.get_result())


(n, m) = map(int, input().split())
if m == 1 and n == 1:
	print(1, 1)
if m == 0:
	print(n, n)
else:
	q = m
	counter = 1
	while q > 0:
		q -= counter
		counter += 1
	print(max(0, n - m * 2), max(n - counter, 0))


(n, m) = map(int, input().split())
ans = 0
for i in range(n + 1):
	num = (i - 1) * i / 2
	if m <= num:
		ans = i
		break
print(max(n - m * 2, 0), n - i)


import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
	exit(0)
x = (1 + math.sqrt(1 + 8 * m)) / 2.0
min_component = int(math.ceil(x))
max_isolated_verts = n - min_component
min_isolated_verts = max(0, n - 2 * m)
print(min_isolated_verts, max_isolated_verts)


import math
x = input()
x = x.split()
n = int(x[0])
m = int(x[1])
if m >= n / 2:
	min = 0
else:
	min = n - 2 * m
max = n - math.ceil((2 * m + (2 * m) ** (1 / 2)) ** (1 / 2))
print(str(min) + ' ' + str(max))


import sys
import math
(n, m) = map(int, input().split())
if m == 0:
	print(n, n)
elif n == 1:
	print(n, n)
else:
	store = [0] * (n + 1)
	if m >= n * (n - 1) // 2:
		print('0', '0')
	else:
		for i in range(2, n + 1):
			store[i] += i * (i - 1) // 2
			if m > store[i - 1] and m <= store[i]:
				amax = n - i
		if m < math.ceil(n / 2):
			amin = n - 2 * m
		else:
			amin = 0
		if m == 1:
			amax = n - 2
		elif m == 2:
			amax = n - 3
		print(amin, amax)


import math
(n, m) = map(int, input().split(' '))
maxi = n - math.ceil((1 + math.sqrt(1 + 8 * m)) / 2.0)
mini = n - 2 * m
maxi = max(maxi, 0)
mini = max(mini, 0)
if m == 0:
	mini = n
	maxi = n
print(int(mini), end=' ')
print(int(maxi))


import math
(n, m) = map(int, input().split())
e = m * 2
if e >= n:
	mn = 0
else:
	mn = n - e
l = 0
for i in range(1, n + 1):
	if (n - i) * (n - i - 1) / 2 >= m:
		l = i
print(mn, l)


(n, m) = map(int, input().split())
if n % 2 == 0:
	if m >= n / 2:
		print(0, end=' ')
	else:
		print(n - 2 * m, end=' ')
elif m > n / 2:
	print(0, end=' ')
else:
	print(n - 2 * m, end=' ')
t = 1
num = 0
if m == 0:
	print(n)
else:
	i = 1
	while i <= m:
		i += t
		t += 1
	if i != 1:
		print(n - t)
	else:
		print(n - 2)


def main():
	(n, m) = map(int, input().split())
	min = 0
	max = 0
	if (1 <= n and n <= 10 ** 5) and (0 <= m and m <= int(n * (n - 1) / 2)):
		if m * 2 >= n:
			print('0 ')
		else:
			print(n - m * 2, ' ')
		for i in range(100001):
			if i * (i - 1) // 2 >= m:
				print(n - i)
				break
main()


import math
(n, m) = list(map(int, input().split()))
ans1 = n - m * 2
ans2 = n
a = n * (n - 1) // 2
amount = n - 1
f = int(math.sqrt(2 * m) + 100001)
if m > 0:
	while (f - 1) * (f - 2) // 2 >= m:
		f -= 1
	if n - m * 2 > 0:
		print(ans1, n - f)
	else:
		print(0, n - f)
else:
	print(n, n)


(n, m) = map(int, input().split())
min_v = max(0, n - m * 2)
in_clique = 1
while m > 0:
	m -= in_clique
	in_clique += 1
max_v = n - in_clique + (in_clique == 1)
print(min_v, max_v)


(n, m) = map(int, input().split())
mn = 0
mx = int((m * 2) ** 0.5)
if m >= n // 2 + n % 2:
	mn = 0
else:
	mn = n - m * 2
while mx * (mx - 1) // 2 < m:
	mx += 1
while mx * (mx - 1) // 2 > m:
	mx -= 1
res = m - mx * (mx - 1) // 2
while res > 0:
	res -= mx
	mx += 1
mx = n - mx
print(mn, mx)


def mainA():
	T = int(input())
	for i in range(T):
		(s, a, b, c) = map(int, input().split())
		ans = s // c
		ans += ans // a * b
		print(ans)

def mainB():
	(n, m) = map(int, input().split())
	if m == 0:
		print(n, n)
	else:
		i = 0
		while i * (i - 1) // 2 < m:
			i += 1
		MAX = max(n - i, 0)
		MIN = max(n - m * 2, 0)
		print(MIN, MAX)
mainB()