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.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Numerics;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
using System.Text;
using System.Threading;

namespace AtCoder
{
	public class Program
	{
		public static void Main()
		{
			var nm = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
			int n = nm[0];
			int m = nm[1];

			var ab = new (int a, int b)[n];
			for (int i = 0; i < n; i++) {
				var temp = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
				ab[i] = (temp[0], temp[1]);
			}

			Array.Sort(ab, (x, y) => x.a.CompareTo(y.a));
			var q = new Queue<(int a, int b)>();
			foreach (var item in ab) {
				q.Enqueue(item);
			}

			var pq = new PriorityQueue<(int a, int b), int>(n, x => x.b);
			long ans = 0;
			for (int i = m; i >= 0; i--) {
				while (q.Count > 0 && m - i >= q.Peek().a) {
					pq.Enqueue(q.Dequeue());
				}

				if (pq.Count > 0) {
					var next = pq.Dequeue();
					ans += next.b;
				}
			}

			Console.WriteLine(ans);
		}
	}

	public class PriorityQueue<TObject, TPriority> where TPriority : IComparable<TPriority>
	{
		private readonly Func<TObject, TPriority> selector_;
		private readonly int reverseFactory_;
		private TObject[] heap_;
		private TPriority[] priorities_;

		public TObject Top => heap_[0];
		public int Count { get; private set; }

		public PriorityQueue(
			Func<TObject, TPriority> selector,
			bool reverses = false)
			: this(1024, selector, reverses) { }

		public PriorityQueue(
			int capacity,
			Func<TObject, TPriority> selector,
			bool reverses = false)
		{
			heap_ = new TObject[capacity];
			priorities_ = new TPriority[capacity];
			selector_ = selector;
			reverseFactory_ = reverses ? -1 : 1;
		}

		public void Enqueue(TObject item)
		{
			if (heap_.Length == Count) {
				Extend(heap_.Length * 2);
			}

			var priority = selector_(item);
			heap_[Count] = item;
			priorities_[Count] = priority;
			++Count;

			int c = Count - 1;
			while (c > 0) {
				int p = (c - 1) >> 1;
				if (Compare(priorities_[p], priority) < 0) {
					heap_[c] = heap_[p];
					priorities_[c] = priorities_[p];
					c = p;
				} else {
					break;
				}
			}

			heap_[c] = item;
			priorities_[c] = priority;
		}

		public TObject Dequeue()
		{
			TObject ret = heap_[0];
			int n = Count - 1;

			var item = heap_[n];
			var priority = priorities_[n];
			int p = 0;
			int c = (p << 1) + 1;
			while (c < n) {
				if (c != n - 1 && Compare(priorities_[c + 1], priorities_[c]) > 0) {
					++c;
				}

				if (Compare(priority, priorities_[c]) < 0) {
					heap_[p] = heap_[c];
					priorities_[p] = priorities_[c];
					p = c;
					c = (p << 1) + 1;
				} else {
					break;
				}
			}

			heap_[p] = item;
			priorities_[p] = priority;
			Count--;

			return ret;
		}

		public void Clear() => Count = 0;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private int Compare(TPriority x, TPriority y)
			=> x.CompareTo(y) * reverseFactory_;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void Extend(int newSize)
		{
			var newHeap = new TObject[newSize];
			heap_.CopyTo(newHeap, 0);
			heap_ = newHeap;
			var newPriorities = new TPriority[newSize];
			priorities_.CopyTo(newPriorities, 0);
			priorities_ = newPriorities;
		}
	}
}