A multi-subject competition is coming! The competition has $m$ different subjects participants can choose from. That's why Alex (the coach) should form a competition delegation among his students. 

He has $n$ candidates. For the $i$-th person he knows subject $s_i$ the candidate specializes in and $r_i$ — a skill level in his specialization (this level can be negative!). 

The rules of the competition require each delegation to choose some subset of subjects they will participate in. The only restriction is that the number of students from the team participating in each of the chosen subjects should be the same.

Alex decided that each candidate would participate only in the subject he specializes in. Now Alex wonders whom he has to choose to maximize the total sum of skill levels of all delegates, or just skip the competition this year if every valid non-empty delegation has negative sum.

(Of course, Alex doesn't have any spare money so each delegate he chooses must participate in the competition).


-----Input-----

The first line contains two integers $n$ and $m$ ($1 \le n \le 10^5$, $1 \le m \le 10^5$) — the number of candidates and the number of subjects.

The next $n$ lines contains two integers per line: $s_i$ and $r_i$ ($1 \le s_i \le m$, $-10^4 \le r_i \le 10^4$) — the subject of specialization and the skill level of the $i$-th candidate.


-----Output-----

Print the single integer — the maximum total sum of skills of delegates who form a valid delegation (according to rules above) or $0$ if every valid non-empty delegation has negative sum.


-----Examples-----
Input
6 3
2 6
3 6
2 5
3 5
1 9
3 1

Output
22

Input
5 3
2 6
3 6
2 5
3 5
1 11

Output
23

Input
5 2
1 -1
1 -5
2 -1
2 -1
1 -10

Output
0



-----Note-----

In the first example it's optimal to choose candidates $1$, $2$, $3$, $4$, so two of them specialize in the $2$-nd subject and other two in the $3$-rd. The total sum is $6 + 6 + 5 + 5 = 22$.

In the second example it's optimal to choose candidates $1$, $2$ and $5$. One person in each subject and the total sum is $6 + 6 + 11 = 23$.

In the third example it's impossible to obtain a non-negative sum.

Difficulty: MEDIUM_HARD
Tags: Sorting

Greedy algorithms
Skill types: Sorting

Greedy algorithms

Starter code:

Solutions:
(n, m) = map(int, input().split())
a = [[] for _ in range(m)]
for _ in range(n):
	(x, y) = map(int, input().split())
	a[x - 1].append(y)
o = [0] * n
for i in range(m):
	a[i].sort(reverse=True)
	s = 0
	for j in range(len(a[i])):
		s += a[i][j]
		if s > 0:
			o[j] += s
print(max(0, max(o)))


import math
import sys
input = sys.stdin.readline

def main():
	(n, m) = [int(x) for x in input().split(' ')]
	subjects = {}
	for i in range(n):
		(sub, skill) = [int(x) for x in input().split(' ')]
		if sub not in subjects:
			subjects[sub] = []
		subjects[sub].append(skill)
	for (k, v) in subjects.items():
		subjects[k] = sorted(v, reverse=True)
	best = 0
	iteration = 0
	while len(subjects) > 0:
		cur_sum = 0
		rem = []
		for (sub, group) in subjects.items():
			if iteration != 0:
				group[iteration] += group[iteration - 1]
			if group[iteration] > 0:
				cur_sum += group[iteration]
			if group[iteration] <= 0 or len(group) - 1 == iteration:
				rem.append(sub)
		for i in rem:
			subjects.pop(i)
		best = max(best, cur_sum)
		iteration += 1
	print(best)
main()


(n, m) = map(int, input().split())
N = 10 ** 5 + 1
sbj_count = [0] * N
sbj_skl = [0] * N
sbj_ans = [0] * N
store = [[] for i in range(N)]
for i in range(n):
	(l, r) = map(int, input().split())
	store[l].append(r)
for i in range(N):
	store[i].sort(reverse=True)
for i in range(1, N):
	for j in range(len(store[i])):
		sbj_skl[i] += store[i][j]
		if sbj_skl[i] > 0:
			sbj_ans[j + 1] += sbj_skl[i]
print(max(sbj_ans))


(N, M) = map(int, input().split())
T = [[] for i in range(M)]
num = -float('inf')
ma = 0
for i in range(N):
	(s, r) = map(int, input().split())
	T[s - 1].append(r)
for i in range(M):
	T[i] = sorted(T[i], reverse=True)
	ma = max(ma, len(T[i]))
num = [0] * (N + 1)
for j in range(M):
	tmp = 0
	for i in range(len(T[j])):
		tmp += T[j][i]
		if tmp < 0:
			break
		num[i] += tmp
print(max(num))


(n, m) = map(int, input().split())
vec = [[] for j in range(100007)]
vt = [[] for j in range(100007)]
cv = set()
for i in range(n):
	(s, r) = map(int, input().split())
	vec[s].append(r)
	cv.add(s)
for i in cv:
	vec[i].sort(reverse=True)
	psum = 0
	for j in range(len(vec[i])):
		psum += vec[i][j]
		vt[j].append(psum)
ans = 0
for i in range(100007):
	if len(vt[i]) == 0:
		break
	vt[i].sort(reverse=True)
	tmp = 0
	for j in range(len(vt[i])):
		if (i + 1) * (j + 1) > n or vt[i][j] <= 0:
			break
		tmp += vt[i][j]
	ans = max(ans, tmp)
print(ans)


from sys import stdin, stdout
from math import *
from heapq import *
from collections import *

def inputlistint():
	return [int(x) for x in stdin.readline().split()]

def main():
	(n, m) = inputlistint()
	s = []
	r = []
	f = []
	for _ in range(m + 2):
		f.append([])
	for _ in range(n):
		(a, b) = inputlistint()
		s.append(a)
		r.append(b)
		f[a].append(b)
	f.sort(key=lambda x: len(x), reverse=True)
	for a in f:
		a.sort(reverse=True)
	res = 0
	for k in range(len(f[0])):
		test = 0
		for i in range(m + 1):
			if k >= len(f[i]):
				break
			if k > 0:
				f[i][k] = f[i][k] + f[i][k - 1]
			if f[i][k] > 0:
				test = test + f[i][k]
		res = max(res, test)
	stdout.write(str(res))
	return 0

def __starting_point():
	main()
__starting_point()


(n, m) = map(int, input().split())
a = [None] * n
s = [0] * (max(n, m) + 1)
cnt = [0] * (max(n, m) + 1)
ans = [0] * (max(n, m) + 1)
for i in range(n):
	(x, y) = map(int, input().split())
	a[i] = (x - 1, y)
a = sorted(a, key=lambda x: x[1], reverse=True)
for i in range(n):
	cnt[a[i][0]] += 1
	s[a[i][0]] += a[i][1]
	ans[cnt[a[i][0]]] += max(0, s[a[i][0]])
print(max(ans))


from collections import defaultdict
(n, m) = [int(i) for i in input().split()]
d = defaultdict(lambda : [])
for _ in range(n):
	(a, b) = [int(i) for i in input().split()]
	d[a].append(b)

class node:

	def __init__(self, sub):
		self.sub = sub
	spe = []
	presum = []
	size = 1
final = []
maxsize = 0
l = 0
for (k, v) in d.items():
	o = node(k)
	v.sort(reverse=True)
	o.spe = v
	o.presum = []
	o.presum.append(v[0])
	for e in v[1:]:
		o.presum.append(o.presum[-1] + e)
		o.size += 1
	final.append(o)
	l += 1
	maxsize = max(maxsize, o.size)
ans = 0
start = 0
final.sort(key=lambda o: o.size)
for size in range(maxsize):
	count = 0
	for i in range(l - 1, start - 1, -1):
		o = final[i]
		count += max(0, o.presum[size])
		if o.size > size + 1:
			start = i
	ans = max(ans, count)
print(max(0, ans))


import sys
sys.setrecursionlimit(2000)
from collections import Counter

def __starting_point():
	(n, m) = [int(val) for val in input().split()]
	delagates = {}
	for i in range(n):
		(s, r) = [int(val) for val in input().split()]
		if s in delagates:
			delagates[s].append(r)
		else:
			delagates[s] = [r]
	summs = {}
	for key in delagates:
		delagates[key].sort(reverse=True)
		summ = 0
		for i in range(1, len(delagates[key]) + 1):
			summ += delagates[key][i - 1]
			if summ < 0:
				continue
			if i in summs:
				summs[i] += summ
			else:
				summs[i] = summ
	summs[-1] = 0
	best = max([val for (key, val) in list(summs.items())])
	print(max(best, 0))
__starting_point()


[n, m] = [int(x) for x in input().split()]
raw_skill_levels = [[] for x in range(m + 10)]
for i in range(n):
	[s, r] = [int(x) for x in input().split()]
	raw_skill_levels[s].append(r)
p_skills = []
for i in range(0, m + 1):
	if not raw_skill_levels[i]:
		continue
	sorted_skill_levels = reversed(sorted(raw_skill_levels[i]))
	running_skill = 0
	running_sums = []
	for skill in sorted_skill_levels:
		running_skill += skill
		running_sums.append(running_skill)
	p_skills.append((len(running_sums), running_sums))
p_skills = sorted(p_skills)
p_skills.reverse()
max_score = 0
for i in range(0, p_skills[0][0]):
	score = 0
	for j in range(0, len(p_skills)):
		if p_skills[j][0] <= i:
			break
		if p_skills[j][1][i] > 0:
			score += p_skills[j][1][i]
	max_score = max(max_score, score)
print(max_score)


(n, m) = list(map(int, input().split()))
l = [list() for i in range(m)]
for i in range(n):
	(a, b) = list(map(int, input().split()))
	l[a - 1].append(b)
ss = []
for i in l:
	ii = sorted(i)
	ii.reverse()
	s = 0
	i.clear()
	for c in ii:
		s += c
		if s >= 0:
			i.append(c)
	i.sort()
	ss.append(sum(i))
ind = list(range(m))
s = 0
m = 0
while len(ind) > 0:
	nind = []
	sub = 0
	for i in ind:
		ll = l[i]
		if len(ll) > 0:
			s += ll.pop()
		if len(ll) > 0:
			nind.append(i)
		else:
			sub += ss[i]
	m = max(m, s)
	s -= sub
	ind = nind
print(m)


r = lambda : map(int, input().split())
(n, m) = r()
spe = [[] for i in range(m + 1)]
for _ in range(n):
	(x, y) = map(int, input().split())
	spe[x].append(y)
out = [0] * n
for i in range(1, m + 1):
	spe[i].sort(reverse=True)
	s = 0
	for j in range(len(spe[i])):
		s += spe[i][j]
		if s > 0:
			out[j] += s
print(max(0, max(out)))


(n, m) = list(map(int, input().split()))
(a, s) = ([], [])
for q in range(n):
	d = list(map(int, input().split()))
	a.append(d[0])
	s.append(d[1])
d = {}
for q in range(n):
	if a[q] in d:
		d[a[q]].append(s[q])
	else:
		d[a[q]] = [s[q]]
for q in d:
	d[q].sort(reverse=True)
for q in list(d.values()):
	sum1 = 0
	for q1 in range(len(q)):
		sum1 += q[q1]
		q[q1] = sum1
f = [0] * (len(max(list(d.values()), key=lambda x: len(x))) + 1)
for q in list(d.values()):
	for q1 in range(len(q)):
		if q[q1] > 0:
			f[q1] += q[q1]
print(max(f))


(n, m) = list(map(int, input().split()))
spec = {}
for i in range(n):
	(s, r) = list(map(int, input().split()))
	if s in spec:
		spec[s].append(r)
	else:
		spec[s] = [r]
f = n
cnt = [-1 for i in range(n + 1)]
for (k, cur) in list(spec.items()):
	cur.sort(reverse=True)
	for j in range(1, len(cur)):
		cur[j] += cur[j - 1]
	for j in range(1, len(cur) + 1):
		if cnt[j] == -1:
			cnt[j] = 0
		cnt[j] += max(0, cur[j - 1])
print(max(cnt))


import os
import heapq
import sys
import math
import operator
from collections import defaultdict
from io import BytesIO, IOBase

def inpt():
	return [int(k) for k in input().split()]

def main():
	(n, m) = map(int, input().split())
	d = defaultdict(list)
	for _ in range(n):
		(a, b) = map(int, input().split())
		d[a].append(b)
	temp = defaultdict(int)
	for i in d.keys():
		d[i].sort(reverse=True)
		for j in range(len(d[i])):
			if j == 0:
				if d[i][j] > 0:
					temp[j] += d[i][j]
				continue
			else:
				d[i][j] += d[i][j - 1]
				if d[i][j] > 0:
					temp[j] += d[i][j]
	ans = 0
	for i in temp.keys():
		ans = max(ans, temp[i])
	print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
input = sys.stdin.readline
(n, m) = list(map(int, input().split()))
SR = [list(map(int, input().split())) for i in range(n)]
LIST = [[] for i in range(m + 1)]
for (s, r) in SR:
	LIST[s].append(r)
LENLIST = [0] * (m + 1)
for i in range(1, m + 1):
	LIST[i].sort(reverse=True)
	LENLIST[i] = len(LIST[i])
LISTSUM = [[] for i in range(m + 1)]
for i in range(1, m + 1):
	if LIST[i] == []:
		continue
	LISTSUM[i].append(LIST[i][0])
	for j in range(1, LENLIST[i]):
		LISTSUM[i].append(LISTSUM[i][-1] + LIST[i][j])
LEN = len(max(LIST, key=lambda x: len(x)))
ANS = [0] * LEN
for j in range(1, m + 1):
	for i in range(LENLIST[j]):
		if LISTSUM[j][i] > 0:
			ANS[i] += LISTSUM[j][i]
		else:
			break
print(max(ANS))


from __future__ import print_function
from collections import *
from sys import stdin
from bisect import *
from heapq import *
from math import *
g = lambda : stdin.readline().strip()
gl = lambda : g().split()
gil = lambda : [int(var) for var in gl()]
gfl = lambda : [float(var) for var in gl()]
gcl = lambda : list(g())
gbs = lambda : [int(var) for var in g()]
rr = lambda x: reversed(range(x))
mod = int(1000000000.0) + 7
inf = float('inf')
(n, m) = gil()
sub = [[] for _ in range(m + 1)]
for _ in range(n):
	(si, ri) = gil()
	sub[si].append(ri)
cnt = [[] for _ in range(n + 1)]
for si in range(1, m + 1):
	sub[si].sort(reverse=True)
	sm = 0
	idx = 0
	for c in sub[si]:
		idx += 1
		sm += c
		cnt[idx].append(sm)
ans = 0
for i in range(n + 1):
	cnt[i].sort(reverse=True)
	sm = 0
	for v in cnt[i]:
		sm += v
		ans = max(ans, sm)
print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
s = [[] for _ in range(m)]
size = [0] * m
for _ in range(n):
	(si, ri) = map(int, input().split())
	s[si - 1].append(ri)
	size[si - 1] += 1
sa = max(size)
i = 0
ans = [0] * sa
for i in range(m):
	s[i] = sorted(s[i], reverse=True)
	if s[i] and s[i][0] > 0:
		ans[0] += s[i][0]
	for j in range(1, sa):
		if j < size[i]:
			s[i][j] += s[i][j - 1]
			if s[i][j] > 0:
				ans[j] += s[i][j]
		else:
			break
	i += 1
res = 0
for i in range(sa):
	res = max(res, ans[i])
print(res)


import sys
import math
from collections import defaultdict, deque
(n, m) = map(int, sys.stdin.readline().split())
dic = defaultdict(list)
for i in range(n):
	(s, r) = map(int, sys.stdin.readline().split())
	dic[s].append(r)
l = 0
vis = defaultdict(int)
ans = [0 for _ in range(n)]
for i in dic:
	dic[i].sort()
	dic[i].reverse()
	n = len(dic[i])
	vis[i] = n
	l = max(n, l)
	s = 0
	for j in range(n):
		s += dic[i][j]
		if s > 0:
			ans[j] += s
		dic[i][j] = s
print(max(ans))


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
sub = [[] for i in range(m)]
for j in range(n):
	(a, b) = map(int, input().split())
	sub[a - 1].append(b)
for j in range(m):
	sub[j] = sorted(sub[j], reverse=True)
sub.sort(key=lambda x: len(x))
for i in range(len(sub)):
	for j in range(1, len(sub[i])):
		sub[i][j] += sub[i][j - 1]
ans = 0
la = 0
for i in range(1, n + 1):
	temp = 0
	for j in range(la, m):
		if len(sub[j]) < i:
			la += 1
			continue
		if sub[j][i - 1] > 0:
			temp += sub[j][i - 1]
	ans = max(temp, ans)
print(ans)


import sys, math, queue
MOD = 998244353
sys.setrecursionlimit(1000000)
(n, m) = map(int, input().split())
x = [[] for i in range(m)]
for i in range(n):
	(xi, s) = map(int, input().split())
	x[xi - 1].append(s)
for xi in x:
	xi.sort(reverse=True)
p = [0 for i in range(n)]
for i in range(m):
	s = 0
	for j in range(len(x[i])):
		s += x[i][j]
		p[j] = max(p[j], p[j] + s)
print(max(p))


import sys
from array import array
import typing as Tp

def input():
	return sys.stdin.buffer.readline().decode('utf-8')

def main():
	from collections import defaultdict
	(n, m) = map(int, input().split())
	dd: Tp.Dict[int, Tp.List[int]] = defaultdict(list)
	for (s, r) in (map(int, input().split()) for _ in range(n)):
		dd[s].append(r)
	ans = 0
	size = 1
	keys = list(dd.keys())
	for key in keys:
		dd[key].sort(reverse=True)
		for i in range(1, len(dd[key])):
			dd[key][i] += dd[key][i - 1]
	while keys:
		score = 0
		next_keys = []
		for key in keys:
			if len(dd[key]) >= size and dd[key][size - 1] > 0:
				score += dd[key][size - 1]
				next_keys.append(key)
		ans = max(ans, score)
		keys = next_keys
		size += 1
	print(ans)
main()


(n, m) = map(int, input().split())
abil = []
for i in range(m):
	abil.append([])
for i in range(n):
	(s, r) = map(int, input().split())
	abil[s - 1].append(r)
use = [None] * m
for i in range(m):
	abil[i].sort(reverse=True)
	sumi = 0
	for j in range(len(abil[i])):
		sumi += abil[i][j]
		if sumi <= 0:
			use[i] = (j, i, sumi - abil[i][j])
			break
		if j == len(abil[i]) - 1:
			use[i] = (j + 1, i, sumi)
	if abil[i] == []:
		use[i] = (0, i, 0)
use.sort()
inuse = {i for i in range(m)}
total = 0
remove = 0
persons = 0
best = 0
while len(inuse) > 0:
	while use[remove][0] <= persons:
		inuse.discard(use[remove][1])
		total -= use[remove][2]
		if inuse == set():
			break
		remove += 1
	for guy in inuse:
		total += abil[guy][persons]
	best = max(best, total)
	persons += 1
print(best)


import sys
input = sys.stdin.readline
from collections import defaultdict
(n, m) = map(int, input().split())
member = defaultdict(list)
subject = []
for _ in range(n):
	(s, r) = map(int, input().split())
	member[s].append(r)
	subject.append(s)
subject = list(set(subject))
for s in subject:
	member[s].sort(reverse=True)
S = defaultdict(int)
M = max((len(member[s]) for s in subject))
ans = 0
ans_cand = 0
for i in range(1, M + 1):
	next_subject = []
	for s in subject:
		if i > len(member[s]) or S[s] + member[s][i - 1] <= 0:
			ans_cand -= S[s]
		else:
			S[s] += member[s][i - 1]
			ans_cand += member[s][i - 1]
			next_subject.append(s)
	ans = max(ans, ans_cand)
	subject = next_subject
print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
d = [[] for i in range(m)]
for i in range(n):
	(s, r) = map(int, input().split())
	d[s - 1].append(r)
for i in range(m):
	d[i] = sorted(d[i], reverse=True)
d.sort(key=lambda x: len(x))
for i in range(len(d)):
	for j in range(1, len(d[i])):
		d[i][j] += d[i][j - 1]
ind = 0
ans = 0
for i in range(1, n + 1):
	s = 0
	for j in range(ind, m):
		if len(d[j]) < i:
			ind += 1
			continue
		if d[j][i - 1] > 0:
			s += d[j][i - 1]
	ans = max(ans, s)
print(ans)


import math
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
(n, m) = map(int, input().split())
d = dict()
for i in range(n):
	(a, b) = map(int, input().split())
	if a in d:
		d[a].append(b)
	else:
		d.update({a: [b]})
for j in d:
	d[j].sort(reverse=True)
ans = [0] * n
for j in d:
	su = 0
	for k in range(len(d[j])):
		su += d[j][k]
		if su > 0:
			ans[k] += su
print(max(ans))


import sys
input = sys.stdin.readline

def prog():
	(n, m) = map(int, input().split())
	subjects = [[] for i in range(m + 1)]
	bst_team = [0] * (n + 1)
	for i in range(n):
		(sub, skill) = map(int, input().split())
		subjects[sub].append(skill)
	for i in range(m + 1):
		subjects[i].sort(key=lambda x: -x)
		tot = 0
		for j in range(len(subjects[i])):
			tot += subjects[i][j]
			bst_team[j + 1] += max(0, tot)
	print(max(bst_team))
prog()


import sys
from collections import *

def solve(io):
	N = io.read_int()
	M = io.read_int()
	subs = defaultdict(lambda : Subject())
	for i in range(0, N):
		S = io.read_int()
		R = io.read_int()
		subs[S].skills.append(R)
	for sub in subs.values():
		sub.skills.sort(reverse=True)
	subs = subs.values()
	best = 0
	while len(subs) > 0:
		next = []
		score = 0
		for sub in subs:
			if sub.pos >= len(sub.skills):
				continue
			sub.total += sub.skills[sub.pos]
			sub.pos += 1
			if sub.total <= 0:
				continue
			score += sub.total
			next.append(sub)
		best = max(best, score)
		subs = next
	io.println(best)

class Subject:

	def __init__(self):
		self.skills = []
		self.total = 0
		self.pos = 0

class IO:
	in_stream = None
	out_stream = None
	raw = ''
	buf = []
	pos = 0

	def __init__(self, input_stream, output_stream):
		self.in_stream = input_stream
		self.out_stream = output_stream

	def read_to_buffer(self):
		self.raw = self.in_stream.readline().rstrip('\n')
		self.buf = self.raw.split()
		self.pos = 0

	def read_string(self):
		while self.pos == len(self.buf):
			self.read_to_buffer()
		ans = self.buf[self.pos]
		self.pos += 1
		return ans

	def read_int(self):
		return int(self.read_string())

	def read_float(self):
		return float(self.read_string())

	def read_string_array(self, N, offset=0):
		arr = [None] * offset
		for _ in range(0, N):
			arr.append(self.read_string())
		return arr

	def read_int_array(self, N, offset=0):
		arr = [None] * offset
		for _ in range(0, N):
			arr.append(self.read_int())
		return arr

	def read_float_array(self, N, offset=0):
		arr = [None] * offset
		for _ in range(0, N):
			arr.append(self.read_float())
		return arr

	def read_line(self):
		while self.pos == len(self.buf):
			self.read_to_buffer()
		if self.pos > 0:
			raise ValueError('Cannot call read_line in the middle of a line.')
		self.pos = len(self.buf)
		return self.raw

	def print(self, *args):
		self.out_stream.write(' '.join([str(x) for x in args]))

	def println(self, *args):
		self.print(*args)
		self.print('\n')

	def println_array(self, arr, sep=' '):
		self.println(sep.join((str(x) for x in arr)))

	def flush_output(self):
		self.out_stream.flush()
pythonIO = IO(sys.stdin, sys.stdout)
solve(pythonIO)
pythonIO.flush_output()


best = [0 for i in range(100003)]
vec = [[] for i in range(100003)]
(n, m) = map(int, input().split())
for i in range(n):
	(s, r) = map(int, input().split())
	vec[s] += [r]
for i in range(1, m + 1):
	list.sort(vec[i])
	list.reverse(vec[i])
	sm = 0
	for j in range(0, len(vec[i])):
		sm += vec[i][j]
		best[j + 1] += max(sm, 0)
res = 0
for i in range(1, n + 1):
	res = max(best[i], res)
print(res)


(n, k) = map(int, input().split())
arr = [[] for _ in range(k)]
for i in range(n):
	(s, r) = map(int, input().split())
	arr[s - 1].append(r)
team_size = [0] * n
for i in range(k):
	suma = 0
	arr[i].sort(reverse=True)
	for j in range(len(arr[i])):
		suma += arr[i][j]
		if suma < 0:
			break
		team_size[j] += suma
print(max(max(team_size), 0))


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

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

def li():
	return list(mi())
(n, m) = mi()
a = [[] for i in range(m + 1)]
for i in range(n):
	(s, r) = mi()
	a[s].append(r)
ch = [0] * (n + 1)
for i in range(1, m + 1):
	a[i].sort(reverse=True)
	pr = 0
	for j in range(len(a[i])):
		pr += a[i][j]
		if pr > 0:
			ch[j + 1] += pr
ans = max(ch)
print(ans)


from collections import defaultdict, deque
(n, m) = map(int, input().split())
skarr = [tuple(map(int, input().split())) for _ in range(n)]
dct = defaultdict(lambda : [])
for (s, r) in skarr:
	dct[s].append(r)
for (k, v) in dct.items():
	v.sort(reverse=True)
	dp = v[0]
	for i in range(1, len(v)):
		dp += v[i]
		v[i] = dp
vs = deque(sorted(dct.values(), key=lambda x: len(x)))
ps = [0]
i = 0
while vs:
	s = 0
	for v in vs:
		s += v[i] if v[i] > 0 else 0
	ps.append(s)
	i += 1
	while vs and i == len(vs[0]):
		vs.popleft()
print(max(ps))


3.5
(N, M) = [*list(map(int, input().split()))]
_L = [list() for i in range(0, M)]
for i in range(0, N):
	(s, r) = [*list(map(int, input().split()))]
	_L[s - 1].append(r)
L = []
L_sum = []
for x in _L:
	if len(x) != 0:
		x.sort(reverse=True)
		L.append(x)
L.sort(reverse=True, key=lambda x: len(x))
for x in L:
	_s = [0] * len(x)
	_s[0] = x[0]
	for i in range(1, len(x)):
		_s[i] = _s[i - 1] + x[i]
	L_sum.append(_s)
ret = 0
for i in range(1, N + 1):
	cpt = 0
	for j in range(0, len(L)):
		if len(L[j]) < i:
			break
		if L_sum[j][i - 1] > 0:
			cpt += L_sum[j][i - 1]
	ret = max(ret, cpt)
print(max(0, ret))


(n, m) = map(int, input().split())
x = [[] for i in range(m)]
for i in range(n):
	(p, q) = map(int, input().split())
	x[p - 1].append(q)
for i in range(len(x)):
	x[i].sort(reverse=True)
an = [0] * n
for i in range(len(x)):
	s = 0
	for j in range(len(x[i])):
		s += x[i][j]
		if s < 0:
			break
		an[j] += s
print(max(an))


while True:
	try:

		def read():
			(cndit, sub) = map(int, input().split())
			info = [[] for i in range(sub + 1)]
			for i in range(cndit):
				(s, sk) = map(int, input().split())
				info[s].append(sk)
			skills = [0] * (cndit + 1)
			for i in range(1, sub + 1, 1):
				info[i].sort(reverse=True)
				summ = 0
				for j in range(len(info[i])):
					summ += info[i][j]
					skills[j + 1] = skills[j + 1] + max(summ, 0)
			skills.sort(reverse=True)
			print(skills[0])
		if __name__ == '__main__':
			read()
	except EOFError:
		break


from sys import stdin
from collections import defaultdict
import operator

def input():
	return stdin.readline()
(n, m) = map(int, input().split())
freq = defaultdict(int)
prefix = defaultdict(list)
for i in range(n):
	(subject, skill) = map(int, input().split())
	prefix[subject].append(skill)
	freq[subject] += 1
freq = dict(sorted(freq.items(), key=operator.itemgetter(1)))
ans = defaultdict(int)
for (key, item) in prefix.items():
	item.sort(reverse=True)
	if item[0] > 0:
		ans[0] += item[0]
	for i in range(1, len(item)):
		item[i] += item[i - 1]
		if item[i] > 0:
			ans[i] += item[i]
if len(ans) > 0:
	res = max(ans.values())
	if res < 0:
		print(0)
	else:
		print(res)
else:
	print(0)


def inint():
	return int(input())

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

def main():
	(n, m) = inlist()
	a = [[] for i in range(m + 1)]
	ch = [0] * (n + 1)
	for _ in range(n):
		(i, j) = inlist()
		a[i].append(j)
	for i in range(1, m + 1):
		a[i].sort(reverse=True)
		ch1 = 0
		for j in range(len(a[i])):
			ch1 += a[i][j]
			if ch1 > 0:
				ch[j + 1] += ch1
	print(max(ch))
main()


from collections import Counter
(n, m) = map(int, input().split())
mp = dict()
for i in range(n):
	(a, b) = map(int, input().split())
	if a not in mp:
		mp[a] = list()
	mp[a].append(b)
for v in mp:
	mp[v].sort(reverse=True)
counter = Counter()
for v in mp:
	sm = 0
	for (idx, arrvalue) in enumerate(mp[v]):
		sm += arrvalue
		if sm > 0:
			counter[idx + 1] += sm
mx = 0
if len(counter) > 0:
	mx = max(mx, *counter.values())
print(mx)


import math

def main():
	buf = input()
	buflist = buf.split()
	n = int(buflist[0])
	m = int(buflist[1])
	sr = []
	for i in range(n):
		buf = input()
		buflist = buf.split()
		sr.append((int(buflist[0]) - 1, int(buflist[1])))
	sr = list(reversed(list(sorted(sr, key=lambda x: x[1]))))
	sp_list = []
	for i in range(m):
		sp_list.append([])
	for i in sr:
		sp_list[i[0]].append(i[1])
	sp_list = list(reversed(list(sorted(sp_list, key=lambda x: len(x)))))
	while len(sp_list[-1]) == 0:
		sp_list.pop()
	score_list = []
	for (i, _) in enumerate(sp_list):
		score_list.append(0)
	max_level = 0
	st_idx = 0
	while len(sp_list) > 0:
		level = 0
		for (i, _) in enumerate(sp_list):
			score_list[i] += sp_list[i][st_idx]
			if score_list[i] > 0:
				level += score_list[i]
		if level > max_level:
			max_level = level
		st_idx += 1
		while len(sp_list) > 0:
			if len(sp_list[-1]) <= st_idx:
				sp_list.pop()
				score_list.pop()
			else:
				break
	print(max_level)
main()


(n, m) = map(int, input().split())
skill_to_cand = {i: [] for i in range(m)}
added = [0] * m
for _ in range(n):
	(s, r) = map(int, input().split())
	skill_to_cand[s - 1] += [r]
for i in range(m):
	skill_to_cand[i].sort()
	skill_to_cand[i].reverse()
best = 0
current = 0
for i in range(n):
	for j in list(skill_to_cand.keys()):
		if len(skill_to_cand[j]) > i:
			current += skill_to_cand[j][i]
			added[j] += skill_to_cand[j][i]
			if added[j] < 0:
				del skill_to_cand[j]
				current -= added[j]
		elif len(skill_to_cand[j]) == i:
			del skill_to_cand[j]
			current -= added[j]
	best = max([best, current])
print(best)


(n, m) = map(int, input().split())
a = [[] for i in range(m)]
for _ in range(n):
	(t, s) = map(int, input().split())
	a[t - 1].append(s)
pre = [0] * n
for i in range(m):
	a[i].sort(reverse=True)
	sum = 0
	k = len(a[i])
	for j in range(k):
		sum += a[i][j]
		if sum < 0:
			break
		pre[j] = pre[j] + sum
print(max(max(pre), 0))


(n, m) = list(map(int, input().rstrip().split()))
data = []
for i in range(0, n):
	data.append(list(map(int, input().rstrip().split())))

def mergesortbysecond(l):
	if len(l) == 1:
		return l
	llower = []
	lupper = []
	for i in range(0, int(len(l) / 2)):
		llower.append(l[i])
	for i in range(int(len(l) / 2), len(l)):
		lupper.append(l[i])
	slower = mergesortbysecond(llower)
	supper = mergesortbysecond(lupper)
	b = 0
	u = 0
	sort = []
	while b < len(slower) and u < len(supper):
		if slower[b][1] <= supper[u][1]:
			sort.append(slower[b])
			b = b + 1
		elif supper[u][1] < slower[b][1]:
			sort.append(supper[u])
			u = u + 1
	if b == len(slower):
		for i in range(u, len(supper)):
			sort.append(supper[i])
	elif u == len(supper):
		for i in range(b, len(slower)):
			sort.append(slower[i])
	return sort
sort = mergesortbysecond(data)
bsort = []
for i in range(0, n):
	bsort.append(sort[n - i - 1])
dic = {}
for i in range(0, n):
	if bsort[i][0] in dic:
		dic[bsort[i][0]].append(bsort[i][1])
	else:
		dic[bsort[i][0]] = [bsort[i][1]]
array = []
for i in range(0, n):
	array.append([])
for ele in dic:
	j = 0
	for i in range(0, len(dic[ele])):
		j = j + dic[ele][i]
		array[i].append(j)
array
ma = 0
for i in range(0, len(array)):
	s = 0
	for j in range(0, len(array[i])):
		s = s + max([array[i][j], 0])
	if s > ma:
		ma = s
print(ma)


(n, m) = map(int, input().split())
inp = tuple(([] for _ in range(m)))
for __ in range(n):
	(s, r) = map(int, input().split())
	inp[s - 1].append(r)
for rs in inp:
	rs.sort(reverse=True)
res = 0
inp1 = list(map(iter, inp))
curs = [0] * m
for ___ in range(n):
	cur = 0
	i = 0
	while i < m:
		try:
			curs[i] += next(inp1[i])
			if curs[i] < 0:
				raise StopIteration
			cur += curs[i]
			i += 1
		except StopIteration:
			m -= 1
			try:
				inp1[i] = inp1.pop()
			except IndexError:
				pass
			try:
				curs[i] = curs.pop()
			except IndexError:
				pass
	res = max(res, cur)
print(res)


from sys import stdin
(n, m) = map(int, stdin.readline().strip().split())
adj = [[0, 0] for i in range(max(m, n) + 1)]
dp = [0 for i in range(max(m, n) + 1)]
s = []
for i in range(n):
	(a, b) = map(int, stdin.readline().strip().split())
	s.append([b, a])
s.sort(reverse=True)
ans = 0
for i in range(n):
	(a, b) = (s[i][1], s[i][0])
	adj[a][0] += 1
	adj[a][1] += b
	dp[adj[a][0]] = max(dp[adj[a][0]] + adj[a][1], dp[adj[a][0]])
print(max(dp))


(n, m) = map(int, input().split())
dic = {}
dicount = {}
for i in range(n):
	(s, r) = map(int, input().split())
	if s in dic:
		dic[s].append(r)
		dicount[s] += 1
	else:
		dic[s] = [r]
		dicount[s] = 1
li = [0] * 10 ** 5
for i in dic:
	dic[i].sort(reverse=True)
	if dic[i][0] >= 0:
		li[0] += dic[i][0]
	else:
		continue
	for j in range(1, dicount[i]):
		dic[i][j] += dic[i][j - 1]
		if dic[i][j] >= 0:
			li[j] += dic[i][j]
		else:
			break
print(max(li))


from sys import stdin, stdout
from collections import defaultdict
(n, m) = tuple(map(int, input().split()))
subs = defaultdict(list)
for _ in range(n):
	(s, r) = tuple(map(int, input().split()))
	subs[s].append(r)
mx = float('-inf')
for (key, values) in subs.items():
	prefix_sums = [0]
	for val in sorted(values, reverse=True):
		curr_val = val + prefix_sums[-1]
		if curr_val <= 0:
			break
		prefix_sums.append(curr_val)
	subs[key] = prefix_sums
	mx = max(mx, len(prefix_sums) - 1)
dp = [0] * (mx + 1)
for (key, values) in subs.items():
	for i in range(len(values)):
		dp[i] += values[i]
print(max(dp))


import sys, math
t = 1
for _ in range(t):
	(n, m) = map(int, sys.stdin.readline().split())
	skills = [[] for i in range(m)]
	for i in range(n):
		(a, b) = map(int, sys.stdin.readline().split())
		skills[a - 1].append(b)
	a = [0] * n
	for i in range(m):
		skills[i].sort(reverse=True)
		temp = 0
		for j in range(len(skills[i])):
			temp += skills[i][j]
			a[j] += max(0, temp)
	print(max(a))


import sys
import copy
import random
(n, m) = [int(x) for x in input().split()]
v = [[] for _ in range(m + 2)]
for i in range(n):
	(x, y) = [int(_) for _ in input().split()]
	if x >= len(v):
		print('break here for i =', x)
		break
	v[x].append(y)
mx = [0 for _ in range(100005)]
for i in range(m + 1):
	v[i] = sorted(v[i], reverse=True)
for i in range(m + 1):
	cur = int(0)
	for j in range(len(v[i])):
		cur += v[i][j]
		if cur < 0:
			continue
		mx[j] += cur
print(max(mx))


(n, m) = [int(_) for _ in input().split()]
d = [[] for k in range(m + 1)]
for _ in range(n):
	(s, r) = [int(_) for _ in input().split()]
	d[s].append(r)
max_num = 0
for v in d:
	max_num = max(max_num, len(v))
sums = [0] * max_num
for (i, v) in enumerate(d):
	v.sort(reverse=True)
	s = 0
	for (k, j) in enumerate(v):
		s += j
		if s > 0:
			sums[k] += s
		else:
			break
print(max(sums))


(n, m) = list(map(int, input().split()))
a = [list(map(int, input().split())) for i in range(n)]
b = [[] for i in range(m)]
z = [0] * m
for i in a:
	b[i[0] - 1].append(i[1])
	z[i[0] - 1] += 1
for i in range(m):
	b[i].sort()
c = [0] * max(*list(z + [z[0]]))
for i in b:
	i1 = len(i)
	e = 0
	for j in range(i1 - 1, -1, -1):
		e += i[j]
		if e > 0:
			c[i1 - 1 - j] += e
print(max(*list(c + [c[0]])))


(n, m) = map(int, input().split())
d = {}
keys = []
si = {}
for i in range(n):
	(x, y) = map(int, input().split())
	if x not in d.keys():
		d[x] = list()
		keys.append(x)
	d[x].append(y)
	si[x] = si.get(x, 0) + 1
for i in keys:
	d[i].sort(reverse=True)
a = 0
c = 0
while True:
	f = 0
	an = 0
	k1 = []
	for i in keys:
		if c < si[i]:
			if c == 0:
				if d[i][c] > 0:
					an += d[i][c]
					k1.append(i)
					f = 1
				else:
					pass
			else:
				d[i][c] += d[i][c - 1]
				if d[i][c] > 0:
					an += d[i][c]
					k1.append(i)
					f = 1
				else:
					pass
	a = max(a, an)
	if f == 0:
		break
	keys = k1
	c += 1
print(a)


(n, m) = map(int, input().split())
ans = 0
l = []
aa = [0] * 100008
for i in range(m):
	l.append([])
for i in range(n):
	(a, b) = map(int, input().split())
	l[a - 1].append(b)
for i in range(m):
	l[i].sort(reverse=True)
for i in range(m):
	temp = 0
	for j in range(len(l[i])):
		l[i][j] = temp + l[i][j]
		temp = l[i][j]
		if l[i][j] > 0:
			aa[j] += l[i][j]
print(max(aa))


import bisect
from collections import defaultdict
(n, m) = map(int, input().split())
dp = [[] for _ in range(m + 1)]
for _ in range(n):
	(x, y) = map(int, input().split())
	dp[x].append(y)
l = 0
for i in range(1, m + 1):
	dp[i].sort(reverse=True)
for i in range(1, m + 1):
	for j in range(1, len(dp[i])):
		dp[i][j] += dp[i][j - 1]
ans = [0] * n
for i in range(1, m + 1):
	for j in range(len(dp[i])):
		if dp[i][j] > 0:
			ans[j] += dp[i][j]
print(max(ans))


(n, m) = map(int, input().split())
cand = {}
for i in range(n):
	(subi, candi) = map(int, input().split())
	if subi in cand:
		cand[subi].append(candi)
	else:
		cand[subi] = [candi]
cand = list(cand.values())
maxi = len(max(cand, key=lambda x: len(x)))
mini = len(min(cand, key=lambda x: len(x)))
output = [0] * (maxi + 1)
for c in cand:
	c.sort(reverse=True)
	i = 0
	sum_ = 0
	while sum_ >= 0 and i < len(c):
		sum_ += c[i]
		if sum_ >= 0:
			output[i] += sum_
		i += 1
print(max(output))


import os
import sys
from math import *
from collections import *
from itertools import *
from heapq import *
from bisect import *
from io import BytesIO, IOBase

def vsInput():
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
ALPHA = 'abcdefghijklmnopqrstuvwxyz'
M = 998244353
EPS = 1e-06

def Ceil(a, b):
	return a // b + int(a % b > 0)

def value():
	return tuple(map(int, input().split()))

def array():
	return [int(i) for i in input().split()]

def Int():
	return int(input())

def Str():
	return input()

def arrayS():
	return [i for i in input().split()]
for _ in range(1):
	(n, m) = value()
	have = defaultdict(list)
	for i in range(n):
		(x, y) = value()
		have[x].append(y)
	ans = [0] * n
	for i in have:
		have[i].sort(reverse=True)
		pre = 0
		for j in range(len(have[i])):
			if pre < 0:
				break
			pre += have[i][j]
			ans[j] += max(0, pre)
	print(max(ans))


import os
import sys
import math
from io import BytesIO, IOBase
from fractions import Fraction
from collections import defaultdict
from itertools import permutations
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
(n, m) = map(int, input().split())
sub = [[] for i in range(m + 1)]
for i in range(n):
	(s, r) = map(int, input().split())
	sub[s].append(r)
length = [0] * (n + 1)
for l in sub:
	l.sort(reverse=True)
	for i in range(len(l) - 1):
		l[i + 1] += l[i]
for l in sub:
	for i in range(len(l)):
		if l[i] > 0:
			length[i + 1] += l[i]
		else:
			break
print(max(length))


(numcand, numsub) = (int(i) for i in input().split())
subs = [[] for _ in range(numsub)]
for _ in range(numcand):
	(sub, prof) = (int(i) for i in input().split())
	subs[sub - 1].append(prof)
for sub in subs:
	sub.sort(reverse=True)
subs = [sub for sub in subs if sub and sub[0] > 0]
best = 0
while subs:
	best = max(best, sum((sub[0] for sub in subs)))
	for i in reversed(range(len(subs))):
		if len(subs[i]) == 1 or subs[i][0] + subs[i][1] <= 0:
			subs.pop(i)
		else:
			subs[i][0:2] = [subs[i][0] + subs[i][1]]
print(best)


(n, m) = map(int, input().split())
mas = [[] for i in range(m + 1)]
lenth = [0] * (m + 1)
ans = [0] * (100000 + 1)
kim = [0] * (m + 1)
for i in range(n):
	(s, r) = map(int, input().split())
	mas[s].append(r)
	lenth[s] += 1
ma = max(lenth)
for i in range(m + 1):
	mas[i] = list(reversed(sorted(mas[i])))
for i in range(m + 1):
	for j in range(ma + 1):
		if lenth[i] >= j + 1:
			kim[i] += mas[i][j]
		else:
			break
		if kim[i] > 0:
			ans[j] += kim[i]
ans += [0]
print(max(ans))


import collections
(N, M) = map(int, input().split())
A = []
S = collections.defaultdict(list)
subjects = set()
for i in range(N):
	(s, r) = map(int, input().split())
	S[s].append(r)
	subjects.add(s)
P = collections.defaultdict(list)
maxl = 0
for i in subjects:
	S[i].sort(reverse=True)
	maxl = max(maxl, len(S[i]))
T = collections.defaultdict(int)
for i in subjects:
	levels = S[i]
	t = 0
	for j in range(len(levels)):
		t += levels[j]
		if t < 0:
			break
		T[j] += t
print(max(0, max(T.values() or [0])))


(n, m) = [int(x) for x in input().split()]
skill = {}
for i in range(m):
	skill[i + 1] = []
for i in range(n):
	(a, b) = [int(x) for x in input().split()]
	skill[a].append(b)
answer = [0] * n
for i in range(1, m + 1):
	skill[i].sort(reverse=True)
	counter = 0
	j = 0
	for item in skill[i]:
		counter += item
		if counter > 0:
			answer[j] += counter
		j += 1
print(max(answer))


(n, m) = map(int, input().split())
q = [[] for i in range(m)]
w = [0] * m
for i in range(n):
	(si, ri) = map(int, input().split())
	q[si - 1].append(ri)
	w[si - 1] += 1
v = max(w)
dp = [0] * n
for i in range(len(q)):
	q[i] = list(reversed(sorted(q[i])))
	if q[i] and q[i][0] > 0:
		dp[0] += q[i][0]
	for j in range(1, v):
		if j < w[i]:
			q[i][j] += q[i][j - 1]
			if q[i][j] > 0:
				dp[j] += q[i][j]
		else:
			break
	i += 1
print(max(dp))


import sys
line = sys.stdin.readline().strip().split()
n = int(line[0])
m = int(line[1])
subjects = []
sums_of_skills = [0] * n
for i in range(0, m):
	subjects.append([])
for i in range(0, n):
	line = sys.stdin.readline().strip().split()
	subjects[int(line[0]) - 1].append(int(line[1]))
for i in range(0, m):
	x = sorted(subjects[i], reverse=True)
	j = 0
	y = 0
	while j < len(x):
		y = y + x[j]
		if y > 0:
			sums_of_skills[j] = sums_of_skills[j] + y
			j = j + 1
		else:
			j = len(x)
print(max([0, max(sums_of_skills)]))


(n, m) = [int(x) for x in input().split()]
ans = 0
cur_ans = 0
skills = {}
total_counted = {}
ind = 0
for _ in range(n):
	(sub, skill) = [int(x) for x in input().split()]
	if sub not in skills:
		skills[sub] = []
		total_counted[sub] = 0
	skills[sub].append(skill)
for x in skills:
	skills[x].sort(reverse=True)
while True:
	if len(total_counted) == 0:
		break
	for x in list(total_counted.keys()):
		if len(skills[x]) == ind or total_counted[x] + skills[x][ind] < 0:
			cur_ans -= total_counted[x]
			total_counted.pop(x)
		else:
			cur_ans += skills[x][ind]
			total_counted[x] += skills[x][ind]
	ans = max(ans, cur_ans)
	ind += 1
print(max(0, ans))


from collections import defaultdict
from itertools import accumulate
(n, m) = [int(x) for x in input().split()]
dt = defaultdict(lambda : [])
for i in range(n):
	(sub, lvl) = [int(x) for x in input().split()]
	dt[sub].append(lvl)
for key in dt.keys():
	dt[key].sort(reverse=True)
ans = [0 for i in range(n + 1)]
for key in dt.keys():
	vals = dt[key]
	prefix = list(accumulate(vals))
	for l in range(len(vals)):
		if prefix[l] >= 0:
			ans[l + 1] += prefix[l]
		else:
			break
print(max(ans))


from sys import stdin, stdout
import cProfile, math
from collections import Counter
from bisect import bisect_left, bisect, bisect_right
import itertools
from copy import deepcopy
from fractions import Fraction
import sys, threading
sys.setrecursionlimit(10 ** 6)
threading.stack_size(2 ** 27)
printHeap = str()
memory_constrained = False
P = 10 ** 9 + 7
import sys
sys.setrecursionlimit(10000000)

class Operation:

	def __init__(self, name, function, function_on_equal, neutral_value=0):
		self.name = name
		self.f = function
		self.f_on_equal = function_on_equal

def add_multiple(x, count):
	return x * count

def min_multiple(x, count):
	return x

def max_multiple(x, count):
	return x
sum_operation = Operation('sum', sum, add_multiple, 0)
min_operation = Operation('min', min, min_multiple, 1000000000.0)
max_operation = Operation('max', max, max_multiple, -1000000000.0)

class SegmentTree:

	def __init__(self, array, operations=[sum_operation, min_operation, max_operation]):
		self.array = array
		if type(operations) != list:
			raise TypeError('operations must be a list')
		self.operations = {}
		for op in operations:
			self.operations[op.name] = op
		self.root = SegmentTreeNode(0, len(array) - 1, self)

	def query(self, start, end, operation_name):
		if self.operations.get(operation_name) == None:
			raise Exception('This operation is not available')
		return self.root._query(start, end, self.operations[operation_name])

	def summary(self):
		return self.root.values

	def update(self, position, value):
		self.root._update(position, value)

	def update_range(self, start, end, value):
		self.root._update_range(start, end, value)

	def __repr__(self):
		return self.root.__repr__()

class SegmentTreeNode:

	def __init__(self, start, end, segment_tree):
		self.range = (start, end)
		self.parent_tree = segment_tree
		self.range_value = None
		self.values = {}
		self.left = None
		self.right = None
		if start == end:
			self._sync()
			return
		self.left = SegmentTreeNode(start, start + (end - start) // 2, segment_tree)
		self.right = SegmentTreeNode(start + (end - start) // 2 + 1, end, segment_tree)
		self._sync()

	def _query(self, start, end, operation):
		if end < self.range[0] or start > self.range[1]:
			return None
		if start <= self.range[0] and self.range[1] <= end:
			return self.values[operation.name]
		self._push()
		left_res = self.left._query(start, end, operation) if self.left else None
		right_res = self.right._query(start, end, operation) if self.right else None
		if left_res is None:
			return right_res
		if right_res is None:
			return left_res
		return operation.f([left_res, right_res])

	def _update(self, position, value):
		if position < self.range[0] or position > self.range[1]:
			return
		if position == self.range[0] and self.range[1] == position:
			self.parent_tree.array[position] = value
			self._sync()
			return
		self._push()
		self.left._update(position, value)
		self.right._update(position, value)
		self._sync()

	def _update_range(self, start, end, value):
		if end < self.range[0] or start > self.range[1]:
			return
		if start <= self.range[0] and self.range[1] <= end:
			self.range_value = value
			self._sync()
			return
		self._push()
		self.left._update_range(start, end, value)
		self.right._update_range(start, end, value)
		self._sync()

	def _sync(self):
		if self.range[0] == self.range[1]:
			for op in self.parent_tree.operations.values():
				current_value = self.parent_tree.array[self.range[0]]
				if self.range_value is not None:
					current_value = self.range_value
				self.values[op.name] = op.f([current_value])
		else:
			for op in self.parent_tree.operations.values():
				result = op.f([self.left.values[op.name], self.right.values[op.name]])
				if self.range_value is not None:
					bound_length = self.range[1] - self.range[0] + 1
					result = op.f_on_equal(self.range_value, bound_length)
				self.values[op.name] = result

	def _push(self):
		if self.range_value is None:
			return
		if self.left:
			self.left.range_value = self.range_value
			self.right.range_value = self.range_value
			self.left._sync()
			self.right._sync()
			self.range_value = None

	def __repr__(self):
		ans = '({}, {}): {}\n'.format(self.range[0], self.range[1], self.values)
		if self.left:
			ans += self.left.__repr__()
		if self.right:
			ans += self.right.__repr__()
		return ans

def display(string_to_print):
	stdout.write(str(string_to_print) + '\n')

def primeFactors(n):
	factors = dict()
	for i in range(2, math.ceil(math.sqrt(n)) + 1):
		while n % i == 0:
			if i in factors:
				factors[i] += 1
			else:
				factors[i] = 1
			n = n // i
	if n > 2:
		factors[n] = 1
	return factors

def isprime(n):
	if n < 4:
		return True
	if n % 2 == 0:
		return False
	if n % 3 == 0:
		return False
	i = 5
	w = 2
	while i * i <= n:
		if n % i == 0:
			return False
		i += w
		w = 6 - w
	return True

def test_print(*args):
	if testingMode:
		print(args)

def display_list(list1, sep=' '):
	stdout.write(sep.join(map(str, list1)) + '\n')

def get_int():
	return int(stdin.readline().strip())

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

def get_list():
	return list(map(int, stdin.readline().split()))
memory = dict()

def clear_cache():
	global memory
	memory = dict()

def cached_fn(fn, *args):
	global memory
	if args in memory:
		return memory[args]
	else:
		result = fn(*args)
		memory[args] = result
		return result
TestCases = False
testingMode = False
optimiseForReccursion = False

def comp(li):
	return len(li)

def main():
	(n, m) = get_tuple()
	li = [[] for _ in range(m)]
	res = 0
	for _ in range(n):
		(s, r) = get_tuple()
		li[s - 1].append(r)
	for x in li:
		x.sort(reverse=True)
	li.sort(key=comp, reverse=True)
	for x in li:
		sm = 0
		for (j, el) in enumerate(x):
			x[j] += sm
			sm = x[j]
	for i in range(1, len(li[0]) + 1):
		ans = 0
		for j in li:
			if len(j) < i:
				break
			ans += j[i - 1] if j[i - 1] > 0 else 0
		res = max(res, ans)
	print(res) if res > 0 else print(0)
if TestCases:
	for _ in range(get_int()):
		cProfile.run('main()') if testingMode else main()
else:
	(cProfile.run('main()') if testingMode else main()) if not optimiseForReccursion else threading.Thread(target=main).start()


from collections import defaultdict
(n, m) = map(int, input().split())
D = defaultdict(list)
for i in range(n):
	(a, b) = map(int, input().split())
	D[a].append(b)
MAX = 0
arr = [0] * (n + 5)
for i in range(1, m + 1):
	if D[i]:
		curSum = 0
		D[i].sort(reverse=True)
		for j in range(len(D[i])):
			curSum += D[i][j]
			if curSum < 0:
				break
			arr[j + 1] += curSum
print(max(arr))


import sys
input = sys.stdin.readline

def gcd(a, b):
	if a == 0:
		return b
	return gcd(b % a, a)

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

def main():
	(n, m) = map(int, input().split())
	skill = [[0] for i in range(m + 1)]
	d = {}
	for i in range(n):
		(s, r) = map(int, input().split())
		if s in d:
			d[s].append(r)
		else:
			d[s] = [r]
	for i in d.keys():
		d[i].sort()
		d[i].reverse()
	for i in d.keys():
		for j in d[i]:
			skill[i].append(skill[i][len(skill[i]) - 1] + j)
	ans = [0] * (n + 1)
	for i in range(1, m + 1):
		for j in range(1, len(skill[i])):
			ans[j] = max(ans[j], ans[j] + skill[i][j])
	print(max(ans))
	return
main()


import heapq, itertools, sys
NEGINF = -sys.maxsize
(n, m) = map(int, sys.stdin.readline().split())
skills_of_subject = {}
for i in range(1, m + 1):
	skills_of_subject[i] = []
for i in range(n):
	(s, r) = map(int, sys.stdin.readline().split())
	skills_of_subject[s].append(r)
cumul_subject_score_for_n_participants = {s: list(itertools.accumulate(sorted(skills_of_subject[s], key=lambda x: -x))) for s in skills_of_subject.keys()}
subject_with_atleast_nparts = {0: skills_of_subject.keys()}
for i in range(1, n + 1):
	subject_with_atleast_nparts[i] = list(filter(lambda sid: len(skills_of_subject[sid]) >= i, subject_with_atleast_nparts[i - 1]))
curr_max = 0
for nParticipants in range(1, n + 1):
	subject_army_by_competence = sorted([cumul_subject_score_for_n_participants[s][nParticipants - 1] for s in subject_with_atleast_nparts[nParticipants]], key=lambda x: -x)
	total_competence = 0
	for i in range(len(subject_army_by_competence)):
		total_competence += subject_army_by_competence[i]
		curr_max = max(curr_max, total_competence)
print(curr_max)


def jud(x):
	return x[1]
(n, m) = map(int, input().split())
stu = []
for i in range(n):
	(x, y) = map(int, input().split())
	stu.append([x, y])
stu.sort(key=jud, reverse=True)
best = [0 for i in range(n + 1)]
ti = [0 for i in range(m + 1)]
sumsc = [0 for i in range(m + 1)]
for i in range(n):
	tmp = stu[i]
	ti[tmp[0]] += 1
	sumsc[tmp[0]] += tmp[1]
	if sumsc[tmp[0]] > 0:
		best[ti[tmp[0]]] += sumsc[tmp[0]]
ans = 0
for i in range(n + 1):
	ans = max(ans, best[i])
print(ans)


(n, m) = map(int, input().split())
lists = []
for i in range(m):
	lists.append([])
for i in range(n):
	(s, r) = map(int, input().split())
	lists[s - 1].append(r)
answers = [0] * n
for i in range(m):
	lists[i].sort(reverse=True)
	for j in range(len(lists[i])):
		if j > 0:
			lists[i][j] += lists[i][j - 1]
		if lists[i][j] > 0:
			answers[j] += lists[i][j]
print(max(0, max(answers)))


(n, m) = map(int, input().split())
ls = [[] for i in range(m)]
incl = [-1] * m
for i in range(n):
	(s, r) = map(int, input().split())
	s -= 1
	ls[s].append(r)
for i in range(m):
	ls[i].sort(reverse=True)
	tot = 0
	for x in ls[i]:
		if tot + x >= 0:
			tot += x
			incl[i] += 1
		else:
			break
longest = max([len(x) for x in ls])
(ans, tot) = (0, 0)
check = set([i for i in range(m)])
for idx in range(longest):
	era = []
	for i in check:
		if idx == incl[i] + 1:
			era.append(i)
			tot -= sum([ls[i][j] for j in range(idx)])
		else:
			tot += ls[i][idx]
	for i in era:
		check.remove(i)
	ans = max(ans, tot)
print(ans)


(n, m) = map(int, input().split())
s = [[] for i in range(m)]
for _ in range(n):
	(si, ri) = map(int, input().split())
	s[si - 1].append(ri)
pre = [0] * n
for i in range(m):
	s[i].sort(reverse=True)
	prefix = 0
	k = len(s[i])
	for j in range(k):
		prefix += s[i][j]
		if prefix < 0:
			break
		pre[j] += prefix
print(max(max(pre), 0))


from collections import defaultdict
d = defaultdict(list)

def calc(d, size):
	ans = 0
	for i in d:
		if len(d[i]) >= size:
			ans += sum(d[i][:size])
	return ans
(n, m) = list(map(int, input().split()))
for i in range(n):
	(s, r) = list(map(int, input().split()))
	d[s].append(r)
minn = 10 ** 10
maxx = -1
for i in d:
	temp = d[i]
	temp.sort()
	temp = temp[-1::-1]
	d[i] = temp
	minn = min(minn, len(temp))
	maxx = max(maxx, len(temp))
pos = [0 for i in range(n)]
for i in d:
	total = 0
	ind = 0
	for j in d[i]:
		total += j
		if total > 0:
			pos[ind] += total
		ind += 1
print(max(max(pos), 0))


(n, m) = map(int, input().split())
subjects = [[] for _ in range(m + 1)]
for i in range(n):
	(s, r) = map(int, input().split())
	subjects[s].append(r)
o = [0] * n
for i in range(1, m + 1):
	subjects[i].sort(reverse=True)
	s = 0
	for j in range(len(subjects[i])):
		s += subjects[i][j]
		if s > 0:
			o[j] += s
print(max(0, max(o)))


(n, m) = map(int, input().split())
s = {}
for i in range(0, n):
	(a, b) = map(int, input().split())
	if s.get(a, -1) == -1:
		s[a] = [b]
	else:
		s[a].append(b)
p = [0] * (n + 1)
for i in s:
	zc = 0
	s[i].sort(reverse=True)
	for j in range(0, len(s[i])):
		zc += s[i][j]
		if zc > 0:
			p[j] += zc
zd = 0
for i in range(0, n + 1):
	zd = max(zd, p[i])
print(zd)


(n, m) = [int(x) for x in input().split()]
v = [[] for _ in range(m + 2)]
sz = 0
for i in range(n):
	(x, y) = [int(_) for _ in input().split()]
	if x >= len(v):
		print('break here for i =', x)
		break
	v[x].append(y)
	sz = max(sz, len(v[x]))
mx = [0 for _ in range(sz + 2)]
for i in range(m + 1):
	v[i] = sorted(v[i], reverse=True)
for i in range(m + 1):
	cur = int(0)
	for j in range(len(v[i])):
		cur += v[i][j]
		if cur < 0:
			continue
		mx[j] += cur
print(max(mx))


(n, m) = map(int, input().split())
sub = [[] for i in range(m + 1)]
for i in range(n):
	(s, r) = map(int, input().split())
	sub[s].append(r)
length = [0] * (n + 1)
for l in sub:
	l.sort(reverse=True)
	for i in range(len(l) - 1):
		l[i + 1] += l[i]
for l in sub:
	for i in range(len(l)):
		if l[i] > 0:
			length[i + 1] += l[i]
		else:
			break
print(max(length))


def main():
	(n, m) = map(int, input().split())
	d = {}
	for _ in range(n):
		(s, r) = map(int, input().split())
		if s in d:
			d[s].append(r)
		else:
			d[s] = [r]
	max_len = 0
	for k in d:
		max_len = max(max_len, len(d[k]))
		d[k].sort(reverse=True)
	l = [0] * max_len
	for k in d:
		su = 0
		for i in range(len(d[k])):
			su += d[k][i]
			if su <= 0:
				break
			l[i] += su
	print(max(l))
main()


import os
import sys
from io import BytesIO, IOBase
import string
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def solve():
	(n, m) = [int(x) for x in input().split(' ')]
	p_dict = {}
	for p in range(n):
		(s, r) = [int(x) for x in input().split(' ')]
		if s in p_dict:
			p_dict[s].append(r)
		else:
			p_dict[s] = [r]
	ans = [0] * n
	for k in p_dict:
		v = sorted(p_dict[k], reverse=True)
		p = 0
		for (i, x) in enumerate(v):
			p += x
			if p > 0:
				ans[i] += p
			else:
				break
	return max(ans)
print(solve())


from sys import stdin
(n, m) = map(int, input().split())
d = [[] for i in range(m + 1)]
for i in range(n):
	(a, b) = (int(x) for x in stdin.readline().split())
	d[a] += [b]
for i in range(1, m + 1):
	d[i].sort(reverse=True)
for i in range(1, m + 1):
	for j in range(1, len(d[i])):
		d[i][j] += d[i][j - 1]
l = [0] * 100001
for i in range(1, m + 1):
	for j in range(len(d[i])):
		if l[j] + d[i][j] < l[j]:
			break
		l[j] = l[j] + d[i][j]
print(max(l))


from sys import stdin, stdout
import math
from itertools import accumulate
(N, M) = [int(x) for x in stdin.readline().split()]
sub = {}
freq = {}
K = {}
for i in range(100005):
	K[i] = []
for i in range(N):
	(s, score) = [int(x) for x in stdin.readline().split()]
	if s not in freq:
		freq[s] = 1
		sub[s] = [score]
	else:
		freq[s] += 1
		sub[s].append(score)
for s in sub:
	sub[s].sort(reverse=True)
	sub[s] = list(accumulate(sub[s]))
	for i in range(len(sub[s])):
		K[i].append(sub[s][i])
res = 0
for i in range(100005):
	if not K[i]:
		break
	s = 0
	for num in K[i]:
		if num > 0:
			s += num
	res = max(res, s)
print(res)


(num_students, num_cats) = [int(x) for x in input().split()]
cats = [[] for _ in range(num_cats)]
for _ in range(num_students):
	(cat_idx, skill) = [int(x) for x in input().split()]
	cat_idx -= 1
	cats[cat_idx].append(skill)
for cat in cats:
	cat.sort(key=lambda x: -x)
entries = []
for cat in cats:
	team_size = 0
	team_skill = 0
	for skill in cat:
		team_size += 1
		team_skill += skill
		entries.append((team_size, -team_skill))
entries.sort()
best_skill = 0
total_skill = 0
curr_size = 1
for entry in entries:
	(size, neg_skill) = entry
	skill = -neg_skill
	if size != curr_size:
		best_skill = max(total_skill, best_skill)
		curr_size = size
		total_skill = 0
	if skill > 0:
		total_skill += skill
best_skill = max(total_skill, best_skill)
print(best_skill)


from operator import attrgetter

class Candidate:
	subject = 0
	hability = 0
en = list(map(int, input().split()))
n = en[0]
m = en[1]
candidates = []
for i in range(n):
	en = list(map(int, input().split()))
	obj = Candidate()
	obj.subject = en[0]
	obj.hability = en[1]
	candidates.append(obj)
candidates.sort(key=attrgetter('subject'))
obj = Candidate()
matrix = [obj] * m
for i in range(m):
	matrix[i] = [obj]
sent = candidates[0].subject
j = 0
for i in range(n):
	if sent != candidates[i].subject:
		sent = candidates[i].subject
		matrix[j].pop(0)
		j += 1
		matrix[j].append(candidates[i])
	else:
		matrix[j].append(candidates[i])
matrix[j].pop(0)
lengths = []
for i in range(len(matrix)):
	matrix[i].sort(key=attrgetter('hability'), reverse=True)
	lengths.append(len(matrix[i]))
max_length = max(lengths)
sums = []
for i in range(max_length + 1):
	sums.append(0)
for i in range(len(matrix)):
	counter = 0
	for j in range(len(matrix[i])):
		counter += matrix[i][j].hability
		if counter < 0:
			break
		sums[j] += counter
print(max(sums))


(n, m) = [int(v) for v in input().split()]
d = [None]
A = [0] * (n + 1)
for i in range(m):
	d.append([])
for i in range(n):
	(s, r) = [int(v) for v in input().split()]
	d[s].append(r)
for td in d[1:]:
	if len(td) == 0:
		continue
	td.sort(reverse=True)
	if td[0] <= 0:
		continue
	prev = 0
	for (j, v) in enumerate(td):
		prev += v
		if prev <= 0:
			break
		A[j] += prev
print(max(A))


(n, m) = map(int, input().split())
candi = [[] for i in range(m)]
for i in range(n):
	(s, r) = map(int, input().split())
	candi[s - 1].append(r)
mlen = 0
for i in range(m):
	if len(candi[i]) > mlen:
		mlen = len(candi[i])
	candi[i].sort(reverse=True)
	for j in range(len(candi[i]) - 1):
		candi[i][j + 1] += candi[i][j]
candi.sort(key=lambda x: len(x), reverse=True)
ans = 0
for i in range(mlen):
	result = 0
	for j in range(m):
		if len(candi[j]) < i + 1:
			break
		if candi[j][i] > 0:
			result += candi[j][i]
	if result > ans:
		ans = result
print(ans)


__author__ = 'tanunia'
from sys import stdin
(n, m) = [int(k) for k in stdin.readline().split()]
lst = []
for _ in range(n):
	(s, r) = [int(k) for k in stdin.readline().split()]
	lst.append([s - 1, r])
lst = sorted(lst, key=lambda x: -x[1])
students_num = [[0, 0] for _ in range(m)]
best_score = [0 for _ in range(n + 1)]
for it in lst:
	(sub, rating) = (it[0], it[1])
	students_num[sub][0] += rating
	students_num[sub][1] += 1
	if students_num[sub][0] > 0:
		best_score[students_num[sub][1]] += students_num[sub][0]
print(max(best_score))


(n, m) = map(int, input().split())
vec = [[] for j in range(m)]
vt = [[] for j in range(n)]
for i in range(n):
	(s, r) = map(int, input().split())
	vec[s - 1].append(r)
for i in range(m):
	vec[i].sort(reverse=True)
	psum = 0
	for j in range(len(vec[i])):
		psum += vec[i][j]
		vt[j].append(psum)
ans = 0
for i in range(n):
	tmp = 0
	for j in range(len(vt[i])):
		if vt[i][j] > 0:
			tmp += vt[i][j]
	ans = max(ans, tmp)
print(ans)


def fastio():
	import sys
	from io import StringIO
	from atexit import register
	global input
	sys.stdin = StringIO(sys.stdin.read())
	input = lambda : sys.stdin.readline().rstrip('\r\n')
	sys.stdout = StringIO()
	register(lambda : sys.__stdout__.write(sys.stdout.getvalue()))
fastio()
MOD = 10 ** 9 + 7
I = lambda : list(map(int, input().split()))
from math import *
(n, m) = I()
l = [[] for i in range(100005)]
a = [0] * 100005
for i in range(n):
	(x, y) = I()
	l[x].append(y)
k = 0
for i in range(m + 1):
	l[i].sort(reverse=True)
maaaaxxxxx = 0
for i in range(1, m + 1):
	k = len(l[i])
	maaaaxxxxx = max(maaaaxxxxx, k)
	for j in range(1, k):
		l[i][j] += l[i][j - 1]
l.sort(key=lambda x: len(x), reverse=True)
ans = 0
for i in range(maaaaxxxxx):
	cur = 0
	for j in range(m):
		if i < len(l[j]):
			cur = max(cur, cur + l[j][i])
		else:
			break
	ans = max(ans, cur)
print(ans)


(n, m) = map(int, input().split())
a = [[] for _ in range(m)]
for _ in range(n):
	(x, y) = map(int, input().split())
	a[x - 1] += (y,)
a.sort(key=lambda v: len(v), reverse=1)
for v in a:
	v.sort(reverse=1)
ans = 0
b = [0] * m
for i in range(len(a[0])):
	while m and len(a[m - 1]) <= i:
		m -= 1
	s = 0
	for j in range(m):
		b[j] += a[j][i]
		s += max(0, b[j])
	ans = max(ans, s)
print(ans)


(n, m) = map(int, input().split())
t = {}

class ap:

	def __init__(self, su):
		self.su = su
		self.cum = [0]
		self.le = 0

	def add(self, val):
		self.cum.append(self.cum[-1] + val)
		self.le += 1

	def sort(self, numb):
		if numb >= len(self.cum) or self.cum[numb] < 0:
			return 0
		return self.cum[numb]
f = []
for i in range(n):
	(su, sk) = map(int, input().split())
	f.append([su, sk])
f.sort(key=lambda x: -x[1])
for x in f:
	if x[0] in t.keys():
		t[x[0]].add(x[1])
	else:
		t[x[0]] = ap(x[0])
		t[x[0]].add(x[1])
maxl = 0
for i in t.keys():
	maxl = max(maxl, t[i].le)
h = [0 for i in range(maxl + 1)]
for i in t.keys():
	for j in range(1, t[i].le + 1):
		h[j] += t[i].sort(j)
print(max(h))