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)

/*
csc -debug D.cs && mono --debug D.exe <<< "3 4
4 3
4 1
2 2"
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;

public class HelloWorld {
    public static void SolveCodeForces() {
        var N = cin.NextInt();
        var M = cin.NextInt();

        var tasks = new List<int[]>(); // [days, reward]
        for (var i = 0; i < N; i++) {
            tasks.Add(cin.IntArray());
        }
        tasks.Sort((a, b) => b[0] - a[0]);

// System.Console.WriteLine(new {N, M});
// for (var i = 0; i < tasks.Count; i++)
//     System.Console.WriteLine(tasks[i].Join());

        var pool = new GenericBinaryHeap<int>((a, b) => b - a);

        var ans = 0L;
        for (var len = 1; len <= M; len++) {
            while (tasks.Count > 0 && tasks[tasks.Count - 1][0] <= len) {
                pool.Insert(tasks[tasks.Count - 1][1]);
                tasks.RemoveAt(tasks.Count - 1);
            }
            if (pool.Count > 0) {
                ans += (long)pool.Min;
                pool.DeleteMin();
            }
        }

        System.Console.WriteLine(ans);
    }

    static Scanner cin = new Scanner();
    static StringBuilder cout = new StringBuilder();

    static public void Main () {
        SolveCodeForces();
        // IncreaseStack(SolveCodeForces);
        // System.Console.Write(cout.ToString());
    }

    public static void IncreaseStack(ThreadStart action, int stackSize = 128000000)
    {
        var thread = new Thread(action, stackSize);
        thread.Start();
        thread.Join();
    }
}

public class GenericBinaryHeap<T> : IEnumerable<T>
{
    private readonly Comparison<T> comparisonDelegate;

    private readonly bool needNotifyIndexChange;
    private readonly Action<T, int> notifyIndexChange;

    public GenericBinaryHeap(Comparison<T> comparisonDelegate)
    {
        this.comparisonDelegate = comparisonDelegate;
    }

    public GenericBinaryHeap(Comparison<T> comparsionDelegate, Action<T, int> notifyIndexChange)
        : this(comparsionDelegate)
    {
        this.notifyIndexChange = notifyIndexChange;
        needNotifyIndexChange = true;
    }

    private readonly List<T> array = new List<T>();

    public T Min { get { return array[0]; } }

    public T this[int indexInHeap] { get { return array[indexInHeap]; } }

    public int Count { get { return array.Count; } }

    public void FillRaw(IEnumerable<T> elements)
    {
        array.Clear();
        array.AddRange(elements);

        if (!needNotifyIndexChange) return;
        for (var i = 0; i < array.Count; i++)
            notifyIndexChange(array[i], i);
    }

    public void BubbleUp(int i)
    {
        var k = array[i];

        while (true)
        {
            var pi = (i - 1) / 2;

            if (pi == i || comparisonDelegate(array[pi], k) <= 0)
                break;

            Swap(i, pi);

            i = pi;
        }
    }

    public void Insert(T k)
    {
        var i = array.Count;
        array.Add(k);

        if (needNotifyIndexChange)
            notifyIndexChange(k, i);

        BubbleUp(i);
    }

    public void DeleteMin()
    {
        Remove(0);
    }

    public void Remove(int indexInHeap)
    {
        var i = indexInHeap;

        if (needNotifyIndexChange)
            notifyIndexChange(array[i], -1);

        var k = array[array.Count - 1];
        array[i] = k;
        array.RemoveAt(array.Count - 1);

        if (needNotifyIndexChange)
            notifyIndexChange(k, i);

        while (true)
        {
            var ci = 2 * i + 1;

            if (ci >= array.Count)
                return;

            var left = array[ci];

            if (ci == array.Count - 1)
            {
                if (comparisonDelegate(left, k) < 0)
                    Swap(i, ci);
                return;
            }

            var right = array[ci + 1];

            var lr = comparisonDelegate(left, right);

            var swapme =
                (lr <= 0 && comparisonDelegate(left, k) < 0)
                    ? ci
                    : (lr > 0 && comparisonDelegate(right, k) < 0)
                            ? (ci + 1)
                            : -1;

            if (swapme == -1)
                return;

            Swap(i, swapme);
            i = swapme;
        }
    }

    private void Swap(int i, int j)
    {
        var tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;

        if (!needNotifyIndexChange) return;

        notifyIndexChange(array[i], i);
        notifyIndexChange(array[j], j);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return array.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public static class Helpers {
    public static string Join<T>(this IEnumerable<T> arr, string sep = " ") {
        return string.Join(sep, arr);
    }

    public static void Swap<T>(ref T a, ref T b) {
        var tmp = a;
        a = b;
        b = tmp;
    }

    public static T[] CreateArray<T>(int length, Func<int, T> itemCreate) {
        var result = new T[length];
        for (var i = 0; i < result.Length; i++)
            result[i] = itemCreate(i);
        return result;
    }
}

public class Scanner
{
    private string[] line = new string[0];
    private int index = 0;

    public string Next() {
        if (line.Length <= index) {
            line = Console.ReadLine().Split(' ');
            index = 0;
        }
        var res = line[index];
        index++;
        return res;
    }

    public int NextInt() {
        return int.Parse(Next());
    }

    public long NextLong() {
        return long.Parse(Next());
    }

    public ulong NextUlong() {
        return ulong.Parse(Next());
    }

    public string[] Array() {
        line = Console.ReadLine().Split(' ');
        index = line.Length;
        return line;
    }

    public int[] IntArray(int emptyPrefixLen = 0) {
        var array = Array();
        var result = new int[emptyPrefixLen + array.Length];
        for (int i = 0; i < array.Length; i++)
            result[emptyPrefixLen + i] = int.Parse(array[i]);
        return result;
    }

    public long[] LongArray() {
        var array = Array();
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
            result[i] = long.Parse(array[i]);
        return result;
    }

    public ulong[] UlongArray() {
        var array = Array();
        var result = new ulong[array.Length];
        for (int i = 0; i < array.Length; i++)
            result[i] = ulong.Parse(array[i]);
        return result;
    }
}