#include <bits/stdc++.h>
using namespace std;

typedef long long ll; // -9,223,372,036,854,775,808 から 9,223,372,036,854,775,807

template <class T> using vec = std::vector<T>;
template <class T> using vec2 = vec<vec<T>>;
template <class T> using vec3 = vec<vec<vec<T>>>;

#define DEBUG

struct Work{
    ll money;
    ll delay;
};

class Fenwick{
    public:
    ll size;
    vec<ll> data;

    Fenwick(int N){
        size = 1;
        while(size < N){
            size *= 2;
        }
        data = vec<ll>(2*size);
    }

    void add_(int k){
        if(k == 0){
            return;
        }
        data.at(k)++;
        add_(k/2);
    }

    void add(int k){
        add_(k + size);
    }

    ll get(int s, int t, int k=1, int l=0, int r=-1){
        r = (r == -1 ? size : r);

        if(t <= l || r <= s){
            return 0;
        }

        if(s <= l && r <= t){
            return data.at(k);
        }

        return get(s, t, 2*k, l, (l+r)/2) + get(s, t, 2*k + 1, (l+r)/2, r);
    }
};

void solve(long long N, long long M, std::vector<long long> A, std::vector<long long> B){
    vec<Work> works;
    for(int i=0; i < N; i++){
        works.push_back(Work{B.at(i), A.at(i)});
    }

    sort(works.begin(), works.end(), [](Work a, Work b){return a.money > b.money;});  // aがbより先頭にくるときtrueになるように。これだと大きいほうが先頭。


    Fenwick fw(M);
    ll Nfilled = 0;
    ll earning = 0;
    // vec<bool> occupied(M, false); // 0番は残り1日のものだけが入れる。i番はのこり(i+1)日のものだけがはいれる。
    for(auto w: works){
        // wがおさまる一番しめりいぎりぎりの日をもとめる
        // occupied[i] == false かつ i >= w - 1なるiで最小のもの
        // あとではやくする
        // for(int i=0; i < M; i++){
        //     if(occupied.at(i) == false && i >= w.delay - 1){
        //         occupied.at(i) = true;
        //         earning += w.money;
        //         Nfilled++;
        //         break;
        //     }
        // }
        ll ok = min(w.delay - 1, M);
        ll ng = M+1;
        while(abs(ng - ok) > 1){
            ll piv = (ok + ng)/2;
            // cout << "hoge" << fw.get(w.delay - 1, piv) << endl;
            if(fw.get(w.delay - 1, piv) == piv - (w.delay - 1)){
                // ng
                ok = piv;
            }else{
                ng = piv;
            }
        }
        if(!(0 <= ok && ok < M)){
            continue;
        }
        // cout << "ok" << ok << " " << (fw.data.at(ok + fw.size) == 0) << endl;
        assert(!(0 <= ok && ok < M) || fw.get(w.delay - 1, ok) == ok - (w.delay - 1));

        if(0 <= ok && ok < M){
            earning += w.money;
            assert(fw.data.at(ok + fw.size) == 0);
            fw.add(ok);
            Nfilled++;
        }


        if(Nfilled == M){
            break;
        }

        // for(auto x: fw.data){
        //     cout << x << " ";
        // }
        // cout << endl;
    }

    cout << earning << endl;

}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
int main(){
    long long N;
    scanf("%lld",&N);
    long long M;
    scanf("%lld",&M);
    std::vector<long long> A(N);
    std::vector<long long> B(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&A[i]);
        scanf("%lld",&B[i]);
    }
    solve(N, M, std::move(A), std::move(B));
    return 0;
}


Measured memory_bytes: 5616