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 Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)

import java.util.*;
import java.util.stream.*;

public class Main {
  
  private static boolean DEBUG = false;
  
  private static void debug(String msg) {
    if ( DEBUG == false ) {
      return;
    }
    System.out.println(msg);
  }
  
  public static void main(String[] args) {
	int N, M;
    Arbeit[] arb;
    try(Scanner sc = new Scanner(System.in)) {
      N = sc.nextInt();
      M = sc.nextInt();
      arb = new Arbeit[N];
      for(int i = 0; i < N; i++) {
        arb[i] = new Arbeit(sc.nextInt(), sc.nextInt());
      }
    }
    int answer = new Solver().solve(M, arb);
    System.out.println(answer);
  }
  
  private static class Arbeit implements Comparable<Arbeit> {
    private final int A;
    private final int B;
    
    public Arbeit(int A, int B) {
      this.A = A;
      this.B = B;
    }
    
    @Override
    public String toString() {
      return new StringBuilder()
        			.append("[").append(A).append(",").append(B).append("]")
        		.toString();
    }
    
    @Override
    public int hashCode() {
      int result = 17;
      result = 31 * result + A;
      result = 31 * result + B;
      return result;
    }
    
    @Override
    public int compareTo(Arbeit o) {
      if ( o == null ) {
        return 1;
      }
      if ( B < o.B ) {
        return 1;
      }
      else if ( B > o.B ) {
        return -1;
      }
      if ( A < o.A ) {
        return -1;
      }
      else if ( A > o.A ) {
        return 1;
      }
      return 0;
    }
    
  }
  
  private static class ArbeitMap {
    
    private final PriorityQueue<Arbeit> pq;
    
    private final Map<Integer,Set<Arbeit>> map;
    
    public ArbeitMap(Arbeit[] arb) {
      pq = new PriorityQueue<>();
      map = new HashMap<>();
      for ( Arbeit a : arb ) {
        int key = a.A;
        Set<Arbeit> set = map.get(key);
        if ( set == null ) {
          set = new HashSet<>();
          map.put(key, set);
        }
        set.add(a);
      }
    }
    
    public String toDumpString() {
      return new StringBuilder()
        			.append("q=").append(pq)
        		.toString();
    }
    
    public Arbeit getMaxReturnArbeit(int i) {
      Set<Arbeit> set = map.get(i);
      if ( set != null ) {
        pq.addAll(set);
        debug(toDumpString());
      }
      if ( pq.isEmpty() ) {
        return null;
      }
      return pq.poll();
    }
  }

  private static class Solver {
    
    public int solve(int m, Arbeit[] arb) {
      ArbeitMap arbMap = new ArbeitMap(arb);
      int value = 0;
      for(int i = 1; i <= m; i++) {
        debug(arbMap.toDumpString());
        Arbeit a = arbMap.getMaxReturnArbeit(i);
        if ( a != null ) {
          debug(a.toString());
          value += a.B;
        }
      }
      return value;
    }
  }
}