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 Rust (1.15.1) (judge verdict: Accepted)

use std::borrow::{Borrow, BorrowMut};
use std::collections::BinaryHeap;
use std::fs::File;
use std::io::{stdout, BufWriter, Read, Write};
use std::thread;

fn main() {
    thread::Builder::new()
        .stack_size(32 * 1024 * 1024) // 32MB
        .spawn(run)
        .unwrap()
        .join()
        .unwrap();
}

/// ローカル環境なら _in.txt から入力を受ける
fn read_input() -> String {
    let stdin = std::io::stdin();
    let mut s = String::new();
    match option_env!("LOCAL") {
        Some(_) => File::open("src/_in.txt")
            .expect("File not found")
            .read_to_string(&mut s)
            .unwrap(),
        None => stdin.lock().read_to_string(&mut s).unwrap(),
    };
    s
}

fn run() {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    let input = read_input();
    let mut input = input.split_whitespace();

    let in_n: i64 = input.next().unwrap().parse().unwrap();
    let in_m: i64 = input.next().unwrap().parse().unwrap();
    let mut ab: Vec<(i64, i64)> = (0..in_n)
        .map(|_| {
            let r: Vec<i64> = input
                .borrow_mut()
                .take(2 as usize)
                .map(|s| s.parse().unwrap())
                .collect();
            (r[0], r[1])
        })
        .collect();

    ab.sort();
    let mut ans = 0;
    let mut i: usize = 0;
    let mut heap: BinaryHeap<i64> = BinaryHeap::new();
    for d in 1..in_m + 1 {
        // a が d のやつを入れられる
        while i < ab.len() && ab[i].0 <= d {
            heap.push(ab[i].1);
            i += 1;
        }
        if let Some(reward) = heap.pop() {
            ans += reward;
        }
    }
    writeln!(out, "{}", ans).ok();
}