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 heap = new (int a, int b)[n];
			int count = 0;

			void Enqueue((int a, int b) item)
			{
				heap[count] = item;
				++count;

				int me = count - 1;
				while (me > 0) {
					int p = (me - 1) / 2;
					if (heap[p].b < item.b) {
						heap[me] = heap[p];
						me = p;
					} else {
						break;
					}
				}

				heap[me] = item;
			}

			(int a, int b) Dequeue()
			{
				var ret = heap[0];
				int n = count - 1;

				var item = heap[n];
				int me = 0;
				int c = me * 2 + 1;
				while (c < n) {
					if (c != n - 1 && heap[c].b < heap[c + 1].b) {
						++c;
					}

					if (item.b < heap[c].b) {
						heap[me] = heap[c];
						me = c;
						c = c * 2 + 1;
					} else {
						break;
					}
				}

				heap[me] = item;
				--count;

				return ret;
			}


			long ans = 0;
			for (int i = m; i >= 0; i--) {
				while (q.Count > 0 && m - i >= q.Peek().a) {
					Enqueue(q.Dequeue());
				}

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

			Console.WriteLine(ans);
		}
	}
}