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 static System.Console;
using static System.Math;
using System.IO;
using System.Collections.Generic;
namespace I_am_the_green_coder{
    class ComparableArray2 : IComparable<ComparableArray2>{
        public long[] arr = new long[2];

        public ComparableArray2(long a, long b){
            arr[0] = a; arr[1] = b;
        }

        public int CompareTo(ComparableArray2 other){
            return arr[1].CompareTo(other.arr[1]);
        }
    }
    class Inonoa{
        static void Main(){
            long[] nm = ILongs();
            long[][] ab = ILongLongs(nm[0]);

            Array.Sort(ab,Compare);

            long ans = 0;

            PriorityQueue<ComparableArray2> q = new PriorityQueue<ComparableArray2>();

            int idx = 0;

            for(int i=1;i<nm[1]+1;i++){
                while(idx < nm[0]){
                    if(ab[idx][0]<=i){
                        q.Enqueue(new ComparableArray2(ab[idx][0],ab[idx][1]));
                        idx ++;
                    }else{
                        break;
                    }
                }

                if(q.Count>0){
                    ans += q.Dequeue().arr[1];
                }
            }

            WriteLine(ans);
        }

        static int Compare(long[] a, long[] b){
            return a[0].CompareTo(b[0]);
        }

        static readonly long MOD = 1000000007;

        ///<summary>a_1, a_2, a_3, ...みたいなの</summary>
        static long[] ILongs(){
            string[] s = ReadLine().Split();
            long[] re = new long[s.Length];
            for(long i=0;i<s.Length;i++){
                re[i] = long.Parse(s[i]);
            }
            return re;
        }

        ///<summary>xooxoxoxxoxo...みたいなの</summary>
        static char[] IChars(){
            return ReadLine().ToCharArray();
        }

        ///<summary>n m とかをちょっとはやくかくだけ</summary>
        static string[] IStrings(){
            return ReadLine().Split();
        }

        ///<summary>n行の入力を取ったり</summary>
        static long[][] ILongLongs(long n){
            long[][] re = new long[n][];
            for(long i=0;i<n;i++){
                string[] s = ReadLine().Split();
                re[i] = new long[s.Length];
                for(long j=0;j<s.Length;j++){
                    re[i][j] = long.Parse(s[j]);
                }
            }
            return re;
        }

        ///<summary>n行の文字列を取ったり</summary>
        static char[][] ICharsChars(long n){
            char[][] re = new char[n][];
            for(long i=0;i<n;i++){
                re[i] = ReadLine().ToCharArray();
            }
            return re;
        }
    }
    class PriorityQueue<T> where T : IComparable<T>{
        private List<T> list = new List<T>();

        public long Count{
            get{
                return list.Count;
            }
        }

        public void Enqueue(T elem){
            int c = list.Count;
            list.Add(elem);

            while(c!=0){
                int i = (c-1) /2;

                if(list[c].CompareTo(list[i])>0){
                    T tmp = list[c];
                    list[c] = list[i];
                    list[i] = tmp;
                }
                
                c = i;
            }
        }

        public T Dequeue(){
            int c = list.Count - 1;
            T pop = list[0];
            list[0] = list[c];
            list.RemoveAt(c);

            for(int i=0, j=1; j<c; ){
                if((j != c-1) && (list[j].CompareTo(list[j+1]) < 0)){
                    j ++;
                }

                if(list[i].CompareTo(list[j])<0){
                    T tmp = list[j];
                    list[j] = list[i];
                    list[i] = tmp;
                }

                i = j;
                j = 2*i + 1;
            }

            return pop;
        }
    }
}