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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

namespace D
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] input = Console.ReadLine().Split().Select(i => Convert.ToInt32(i)).ToArray();
            int N = input[0];
            int M = input[1];
            var AB = Enumerable.Repeat(new int[2], N).Select(ab => ab = Console.ReadLine().Split().Select(i => Convert.ToInt32(i)).ToArray());
            var sortedAB = AB.OrderBy(ab => ab[0]).ToArray();
            long ans = 0L;
            int idx = 0;
            int day = 1;
            PriorityQueue<int> pq = new PriorityQueue<int>((a, b) => b - a);
            while (day <= M)
            {
                if (idx < N && sortedAB[idx][0] <= day)
                {
                    while (idx < N && sortedAB[idx][0] <= day)
                    {
                        pq.Enqueue(sortedAB[idx][1]);
                        idx++;
                    }
                }
                if (pq.Any())
                {
                    ans += pq.Dequeue();
                }
                day++;
            }
            Console.WriteLine(ans);
        }
    }

    class PriorityQueue<T>
    {
        readonly List<T> heap;
        // Comparison<T>についてはhttps://docs.microsoft.com/ja-jp/dotnet/api/system.comparison-1?view=netframework-4.8を参照
        readonly Comparison<T> compare;
        private int size;

        public PriorityQueue(Comparison<T> compare)
        {
            heap = new List<T>();
            this.compare = compare;
        }

        /// <summary>
        /// 常に降順を保ったヒープにする
        /// </summary>
        /// <param name="val"></param>
        public void Enqueue(T val)
        {
            heap.Add(val);
            int i = size++;
            while (i > 0)
            {
                int p = (i - 1) >> 1;
                if (compare(heap[p], val) <= 0) break;
                heap[i] = heap[p];
                i = p;
            }
            heap[i] = val;
        }

        public T Dequeue()
        {
            T ret = heap[0];
            T x = heap[--size];
            int i = 0;
            while ((i << 1) + 1 < size)
            {
                int a = (i << 1) + 1;
                int b = (i << 1) + 2;
                if (b < size && compare(heap[b], heap[a]) < 0) a = b;
                if (compare(heap[a], x) >= 0) break;
                heap[i] = heap[a];
                i = a;
            }
            heap[i] = x;
            heap.RemoveAt(size);
            return ret;
        }

        public T Peek() { return heap[0]; }
        public int Count { get { return size; } }
        public bool Any() { return size > 0; }
    }
}