#include <bits/stdc++.h>
    // #include <iostream>
    #include <string>
    #include <queue>
    #include <set>
    #include <list>
    #include <chrono>
    #include <random>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <map>
    #include <unordered_map>
    #include <stack>
    using namespace std;
    #define frn(i,a,b) for(ll i=a;i<b;i++)
    #define forn(i,a,b) for(ll i=a;i<=b;i++)
    #define frt(i,a,b) for(auto it=a;it!=b;it++)
    #define MP make_pair
    #define F first
    #define S second
    #define PB push_back
    #define SQ(a) (a)*(a)
    #define SUM(n) ((n)*(n+1))/2
    #define SqSUM(n) ((n)*(n+1)*(2*n+1))/2
    #define GMSUM(a,r,n) (a*pow(r,n)-a)/(r-1)
    // to sort vector of any kind string or any sorting form sort(v.begin(),v.end()); and for reverse use rbegin and rend
    const long long int md = 998244353;
    typedef long long ll;
    typedef long double ld;
    typedef pair<ll, ll> pi;
    typedef vector<ll> vi;
    typedef vector<vector<ll, ll> > vvi;
    // typedef bitset<5> bst;
    const ll MAX = LONG_MAX;





struct Job 
{ 
    // Each job has id, deadline and profit 
    int id; 
    int deadLine, profit; 
}; 
  
// A Simple Disjoint Set Data Structure 
struct DisjointSet 
{ 
    int *parent; 
  
    // Constructor 
    DisjointSet(int n) 
    { 
        parent = new int[n+1]; 
  
        // Every node is a parent of itself 
        for (int i = 0; i <= n; i++) 
            parent[i] = i; 
    } 
  
    // Path Compression 
    int find(int s) 
    { 
        /* Make the parent of the nodes in the path 
           from u--> parent[u] point to parent[u] */
        if (s == parent[s]) 
            return s; 
        return parent[s] = find(parent[s]); 
    } 
  
    // Makes u as parent of v. 
    void merge(int u, int v) 
    { 
        //update the greatest available 
        //free slot to u 
        parent[v] = u; 
    } 
}; 





bool cmp(Job a, Job b) 
{ 
    return (a.profit > b.profit); 
} 
  
// Functions returns the maximum deadline from the set 
// of jobs 
int findMaxDeadline(struct Job arr[], int n) 
{ 
    int ans = INT_MIN; 
    for (int i = 0; i < n; i++) 
        ans = max(ans, arr[i].deadLine); 
    return ans; 
} 
  
vector<int> printJobScheduling(Job arr[], int n) 
{ 
    // Sort Jobs in descending order on the basis 
    // of their profit 
    sort(arr, arr + n, cmp); 
    vector<int> vv;
    // Find the maximum deadline among all jobs and 
    // create a disjoint set data structure with 
    // maxDeadline disjoint sets initially. 
    int maxDeadline = findMaxDeadline(arr, n); 
    DisjointSet ds(maxDeadline); 
  
    // Traverse through all the jobs 
    for (int i = 0; i < n; i++) 
    { 
        // Find the maximum available free slot for 
        // this job (corresponding to its deadline) 
        int availableSlot = ds.find(arr[i].deadLine); 
  
        // If maximum available free slot is greater 
        // than 0, then free slot available 
        if (availableSlot > 0) 
        { 
            // This slot is taken by this job 'i' 
            // so we need to update the greatest  
            // free slot. Note that, in merge, we  
            // make first parameter as parent of  
            // second parameter. So future queries 
            // for availableSlot will return maximum 
            // available slot in set of  
            // "availableSlot - 1" 
            ds.merge(ds.find(availableSlot - 1),  
                             availableSlot); 
  
            // cout << arr[i].id << " ";
            vv.push_back(arr[i].id);
        } 
    }
    return vv; 
} 





    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout.tie(NULL);
        int n,m;
        cin>>n>>m;
        int ar[n],br[n];
        frn(i,0,n)
        {
            cin>>ar[i]>>br[i];
        }
        Job jr[n];
        frn(i,0,n)
        {
            jr[i].id=i;
            jr[i].deadLine = max(0,m+1-ar[i]);
            jr[i].profit = br[i];
        }
        vector<int> v=printJobScheduling(jr, n);
        ll sm=0;
        for(auto it:v)
        sm+=br[it];
        cout<<sm; 
        return 0;
    } 

Measured memory_bytes: 3196