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 (GCC 5.4.1) (judge verdict: Runtime Error)

#include<stdio.h>
#include<stdlib.h>

#define NEW(p,n){p=malloc((n)*sizeof(p[0]));if(p==NULL){printf("not enough memory\n");exit(1);};}
//pの型の変数n個の要素分のメモリを確保し、そのアドレスをpに代入するマクロ

#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PARENT(i) ((i)/2)

typedef struct{
    int price;
    int date;
}heapdata;

//ヒープ木型の定義
typedef struct{
    int max_size;   //ヒープ二分木(配列A)の中に格納できる最大要素数
    int heap_size;  //ヒープ二分木(配列A)の中に現在入っている要素の数
    heapdata* A;    //要素を格納するための配列(ポインタ)
}* heap;

//ヒープH内の配列のA[i]とA[j]の値を入れ替える関数
void heap_swap(heap H,int i,int j){
    heapdata tmp;
    
    tmp=H->A[i];
    H->A[i]=H->A[j];
    H->A[j]=tmp;
    
    return;
}

//HEAPIFY O(nlogn)
//A[i]を根とする部分木がヒープになるように整序する関数
void heapify(heap H, int i){
    int l,r,largest,size;
    heapdata* A;
    
    l=LEFT(i); //iの左の子の添字
    r=RIGHT(i); //iの右の子の添字
    size=H->heap_size; //今のヒープHのサイズ
    A=H->A; //ヒープ二分木に格納されている要素の配列
    
    //以下largestを決めるコード
    if(l>size&&r>size){
        largest=i;
    }
    else if(l<=size&&r>size){
        if(A[l].price>A[i].price){
            largest=l;
        }
        else{
            largest=i;
        }
    }
    else{
        if(A[r].price>A[l].price){
            largest=r;
        }
        else{
            largest=l;
        }
        if(A[i].price>A[largest].price){
            largest=i;
        }
    }
    
    //largestが決まったら要素を入れ替えする
    if(largest!=i){
        heap_swap(H,i,largest);
        heapify(H,largest);
    }
    
    return;
}

//BUILD_HEAP O(n)
//要素n個の配列A[1]~A[n]、max_sizeをもつヒープ木Hのメモリを確保し出力する関数
heap heap_build(int n, heapdata* A, int max_size){
    int i;
    heap H;
    NEW(H,1);
    
    H->max_size=max_size;
    H->heap_size=n;
    H->A=A;
    
    for(i=n/2;i>=1;i--){
        heapify(H,i);
    }
    
    return H;
}

//EXTRACT_MAX O(logn)
//ヒープ木の中の最大要素を削除し出力、その最大要素を除いたヒープ木を再構成する関数
heapdata extract_max(heap H){
    int n=H->heap_size;
    
    heap_swap(H,1,n);
    H->heap_size=n-1;
    heapify(H,1);
    
    return H->A[n];
}

int main(void){
    int N,M;
    scanf("%d %d",&N, &M);

    //S[1]~S[N]に格納する
    heapdata* S;
    NEW(S,N+1);
    for(int i=1;i<=N;i++){
        scanf("%d %d",&S[i].date, &S[i].price);
    }

    heap T=heap_build(N,S,N);

    long ans=0;
    int day=0;
    while(T->heap_size>0||day<=M){
        heapdata h = extract_max(T);
        if(h.date<=(M-day)){
            ans+=h.price;
            day++;
        }
    }

    //今日が0日目、M日目までに得られる報酬の最大値が欲しい

    printf("%ld\n",ans);

    return 0;
}