Problem:
Score : 400 points

Problem Statement

There are N one-off jobs available. If you take the i-th job and complete it, you will earn the reward of B_i after A_i days from the day you do it.

You can take and complete at most one of these jobs in a day.

However, you cannot retake a job that you have already done.

Find the maximum total reward that you can earn no later than M days from today.

You can already start working today.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq A_i \leq 10^5

1 \leq B_i \leq 10^4

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
A_2 B_2
\vdots
A_N B_N

Output

Print the maximum total reward that you can earn no later than M days from today.

Sample Input 1

3 4
4 3
4 1
2 2

Sample Output 1

5

You can earn the total reward of 5 by taking the jobs as follows:

Take and complete the first job today. You will earn the reward of 3 after four days from today.

Take and complete the third job tomorrow. You will earn the reward of 2 after two days from tomorrow, that is, after three days from today.

Sample Input 2

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

Sample Output 2

10

Sample Input 3

1 1
2 1

Sample Output 3

0

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;

namespace AtCoder.ABC
{
	public class AB : IComparable
	{
		public int A;
		public int B;

		public AB(int[] ab)
		{
			A = ab[0];
			B = ab[1];
		}

		public int CompareTo(object y)
		{
			if(y is null) {
				return 0;
			}

			if(y is AB x) {
				return CompareTo(x);
			}

			throw new NotImplementedException();
		}

		public int CompareTo(AB y)
		{
			return y.B - this.B;
		}
	}

	class QuestionC
	{
		public static void Main(string[] args)
		{
			var nm = Console.ReadLine().Split(" ").Select(x => int.Parse(x)).ToArray();
			var n = nm[0];
			var m = nm[1];

			var ab = new List<AB>();

			for(int i = 0; i < n; i++) {
				ab.Add(new AB(Console.ReadLine().Split(" ").Select(x => int.Parse(x)).ToArray()));
			}

			ab.Sort((x, y) => x.A - y.A);

			var temp = new PriorityQueue<AB>(n);
			var sum = 0L;

			int index = 0;

			for(int remain = 1; remain <= m; remain++) {
				for(; index < n; index++) {
					if (ab[index].A <= remain) {
						temp.Push(ab[index]);
					} else {
						break;
					}
				}

				if (temp.Count() != 0) {
					sum += temp.Pop().B;
				}
			}

			Console.WriteLine(sum);
		}
	}

	public class PriorityQueue<T> where T : IComparable
	{
		private IComparer<T> comparer_;
		private bool isAsc_;

		private T[] heap_;
		private int size_ = 0;
		private int count_ = 0;

		public PriorityQueue(int maxSize, IComparer<T> comparer)
		{
			heap_ = new T[maxSize];
			comparer_ = comparer;
		}

		public PriorityQueue(int maxSize, bool isAsc = true)
		{
			heap_ = new T[maxSize];
			isAsc_ = isAsc;
		}

		private int Compare(T x, T y)
		{
			if (comparer_ is null == false) {
				return comparer_.Compare(x, y);
			}

			return isAsc_ ? x.CompareTo(y) : y.CompareTo(x);
		}

		public void Push(T x)
		{
			count_++;

			var nodeIndex = size_++;

			while (nodeIndex > 0) {
				var parentIndex = (nodeIndex - 1) / 2;

				if (Compare(heap_[parentIndex], x) <= 0) {
					break;
				}

				heap_[nodeIndex] = heap_[parentIndex];
				nodeIndex = parentIndex;
			}

			heap_[nodeIndex] = x;
		}

		public T Pop()
		{
			count_--;

			T ret = heap_[0];
			T x = heap_[--size_];
			heap_[size_] = default;

			int nodeIndex = 0;
			while ((nodeIndex * 2) + 1 < size_) {
				int childrenA = nodeIndex * 2 + 1;
				int childrenB = nodeIndex * 2 + 2;


				if (childrenB < size_ && Compare(heap_[childrenA], heap_[childrenB]) > 0) {
					childrenA = childrenB;
				}

				if (Compare(heap_[childrenA], x) >= 0) {
					break;
				}

				heap_[nodeIndex] = heap_[childrenA];
				nodeIndex = childrenA;
			}

			heap_[nodeIndex] = x;

			return ret;
		}

		public int Count()
		{
			return count_;
		}

		public T Peek()
		{
			return heap_[0];
		}

		public bool Contains(T x)
		{
			for (int i = 0; i < size_; i++) {
				if (x.Equals(heap_[i])) {
					return true;
				}
			}

			return false;
		}

		public void Clear()
		{
			while (Count() > 0) {
				Pop();
			}
		}

		public IEnumerator<T> GetEnumerator()
		{
			var ret = new List<T>();

			while (Count() > 0) {
				ret.Add(Pop());
			}

			foreach (var r in ret) {
				Push(r);
				yield return r;
			}
		}

		public T[] ToArray()
		{
			T[] array = new T[size_];
			int i = 0;

			foreach (var r in this) {
				array[i++] = r;
			}

			return array;
		}
	}
}