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 PHP7 (7.0.15) (judge verdict: Accepted)

<?php

class Pq extends SplPriorityQueue implements JsonSerializable
{
    // [Debug] SplPriorityQueue which returns array<priority, array<data>> when stringified.
    private function toDict()
    {
        $tmp = clone $this;
        $tmp->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
        $dict = [];
        foreach ($tmp as $dp) {
            $dict[$dp['priority']][] = $dp['data'];
        }
        return $dict;
    }
    public function __toString()
    {
        return json_encode(self::toDict());
    }
    public function jsonSerialize()
    {
        return self::toDict();
    }
}

function rline(): string
{
    return trim(fgets(STDIN));
}

function rwords(): array
{
    return explode(' ', rline());
}

function rint(): array
{
    return intval(rline());
}

function rints(): array
{
    return array_map('intval', rwords());
}

function prettifyArray($arr, ...$delimiters):string
{
    // stringify array.
    $d = array_pop($delimiters);
    if (is_array($d)) {
        $delimiters = $d;
        $delimiter = array_pop($delimiters);
    } else {
        $delimiter = $d;
    }
    if (empty($delimiters)) {
        return implode($delimiter, array_map('prettify', $arr));
    }
    return implode($delimiter, array_map(function ($elem) use ($delimiters) {
        return prettifyArray($elem, $delimiters);
    }, $arr));
}

function prettify($var): string
{
    // stringify variable.
    if (!is_array($var)) {
        return strval($var);
    }
    if (is_array(reset($var))) {
        // 2-dimensional array. matrix should I call
        return prettifyArray($var, ' ', PHP_EOL);
    }
    // 1-dimensional array.
    return prettifyArray($var, ' ');
}

function pline($var)
{
    // print line.
    print(prettify($var));
    print(PHP_EOL);
}

function plines(array $arr)
{
    // print lines.
    print(implode(PHP_EOL, array_map('prettify', $arr)));
    print(PHP_EOL);
}

function xrange($start, $endExcl, $step = 1)
{
    // returns range, end exclusive.
    $e = $endExcl - intdiv($step, abs($step));
    if ($start > $e && $step > 0) {
        return [];
    }
    if ($start < $e && $step < 0) {
        return [];
    }
    return range($start, $e, $step);
}

function mdarray($default, ...$sizes)
{
    // returns multi-dimensional array filled with a default value.
    // $default may be a callable which returns an object.
    $s = array_shift($sizes);
    if (is_array($s)) {
        $sizes = $s;
        $size = array_shift($sizes);
    } else {
        $size = $s;
    }
    if (!empty($sizes)) {
        return array_map(function () use ($default, $sizes) {
            return mdarray($default, $sizes);
        }, array_fill(0, $size, null));
    }

    if (is_callable($default)) {
        return array_map($default, array_fill(0, $size, null));
    } elseif (is_object($default)) {
        throw new BadMethodCallException('if you want an object to be the default value, return it in a callable.');
    }
    
    return array_fill(0, $size, $default);
}

function dcarray(array $arr)
{
    // deep copy array.
    $copy = $arr;
    foreach ($copy as $key => &$value) {
        if (is_null($value)) {
            continue;
        } elseif (is_object($value)) {
            $value = clone $value;
        } elseif (is_array($value)) {
            $value = dcarray($value);
        } else {
            continue;
        }
    }
    return $copy;
}

function gcd($a, $b): int
{
    // returns greatest common divisor.
    $x = min($a, $b);
    $y = max($a, $b);
    return $y % $x === 0 ? $x : gcd($y % $x, $x);
}

function pjson(...$vars)
{
    // [Debug] print variables in json format.
    print(json_encode($vars));
    print(PHP_EOL);
}


function solve()
{
    // read here
    list($n, $m) = rints();
    $d = [];
    foreach (xrange(0, $n) as $i) {
        list($a, $b) = rints();
        if (!array_key_exists($a, $d)) {
            $d[$a] = [];
        }
        $d[$a][] = $b;
    }
    // pjson($d);

    // solve here

    $q = new Pq();
    $ans = 0;
    foreach (xrange(0, $m + 1) as $i) {
        foreach ($d[$i] ?? [] as $b) {
            $q->insert($b, $b);
        }
        if (!$q->isEmpty()) {
            $ans += $q->extract();
        }
    }

    // print here
    pline($ans);
}



if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) {
    try {
        solve();
    } catch (Throwable $t) {
        plines([$t->getLine(), $t->getMessage()]);
    }
}