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.Runtime.InteropServices;
using System.Text;

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

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

        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>((x, y) => x.B.CompareTo(y.B));
            var sum = 0L;

            int index = 0;

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

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

            Console.WriteLine(sum);
        }
        public class PriorityQueue<T>
        {
            private readonly List<T> data_ = new List<T>();
            private readonly IComparer<T> comparer_;
            private readonly bool isDescending_;

            public PriorityQueue(IComparer<T> comparer, bool isDescending = true)
            {
                comparer_ = comparer;
                isDescending_ = isDescending;
            }

            public PriorityQueue(Comparison<T> comparison, bool isDescending = true)
                : this(Comparer<T>.Create(comparison), isDescending)
            {
            }

            public PriorityQueue(bool isDescending = true)
                : this(Comparer<T>.Default, isDescending)
            {
            }

            public void Enqueue(T item)
            {
                data_.Add(item);
                var childIndex = data_.Count - 1;
                while (childIndex > 0) {
                    var parentIndex = (childIndex - 1) / 2;

                    if (Compare(data_[childIndex], data_[parentIndex]) >= 0) {
                        break;
                    }

                    Swap(childIndex, parentIndex);
                    childIndex = parentIndex;
                }
            }

            public T Dequeue()
            {
                var lastIndex = data_.Count - 1;
                var firstItem = data_[0];
                data_[0] = data_[lastIndex];
                data_.RemoveAt(lastIndex--);
                var parentIndex = 0;
                while (true) {
                    var childIndex = parentIndex * 2 + 1;

                    if (childIndex > lastIndex) {
                        break;
                    }

                    var rightChild = childIndex + 1;

                    if (rightChild <= lastIndex && Compare(data_[rightChild], data_[childIndex]) < 0) {
                        childIndex = rightChild;
                    }

                    if (Compare(data_[parentIndex], data_[childIndex]) <= 0) {
                        break;
                    }

                    Swap(parentIndex, childIndex);
                    parentIndex = childIndex;
                }
                return firstItem;
            }

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

            private void Swap(int a, int b)
            {
                var tmp = data_[a];
                data_[a] = data_[b];
                data_[b] = tmp;
            }

            private int Compare(T a, T b)
            {
                return isDescending_ ? comparer_.Compare(b, a) : comparer_.Compare(a, b);
            }

            public int Count => data_.Count;
        }
    }
}