#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <set> 
#include <map>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstring>
#include <iomanip>
#define REP(i,n) for(int i=0; i<(n); ++i)
#define FOR(i,a,b) for(int i=(a); i<(b); ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int INF = 100100100;
const ll INFLL = 1001001001001001001;  // > 10^18
const int MOD = (int)1e9 + 7;
const ll MODLL = (ll)1e9 + 7;
const double EPS = 1e-9;

struct SegmentTree {
    int n;
    vector<int> node;
    vector<int> index; // argminも同時に持たせる
    SegmentTree(vector<int> v) {
        int sz = v.size();
        n = 1; while(n < sz) n *= 2;
        //モノイド単位元で初期化する
        node.resize(2*n-1, INF); 
        index.resize(2*n-1, -1);
        //一番下の段にデータを格納
        for(int i=0; i<sz; i++) node[i+n-1] = v[i];
        for(int i=0; i<sz; i++) index[i+n-1] = i;
        //上に昇りながらモノイド演算で情報を構築
        for(int i=n-2; i>=0; i--){
            int minv = min(node[2*i+1], node[2*i+2]);
            if (minv == node[2*i+1]) {
                node[i] = node[2*i+1];
                index[i] = index[2*i+1];
            } else {
                node[i] = node[2*i+2];
                index[i] = index[2*i+2];
            } 
        } 
    }
    void update(int x, int val) {
        //一番下の段でデータを更新
        x += (n - 1); 
        node[x] = val;
        //昇りながら関係各所のデータをモノイド演算で更新
        while(x > 0) {
            x = (x - 1) / 2;
            int minv = min(node[2*x+1], node[2*x+2]);
            if (minv == node[2*x+1]) {
                node[x] = node[2*x+1];
                index[x] = index[2*x+1];
            } else {
                node[x] = node[2*x+2];
                index[x] = index[2*x+2];
            }
        }
    }
    // getmin(a,b) と呼ぶと (min, argmin) を返す関数
    pair<int, int> getmin(int a, int b, int k=0, int l=0, int r=-1) {
        //初回の呼び出し
        if(r < 0) r = n;
        //交わらないときはモノイドの単位元を返す
        if(r <= a || b <= l) return pair<int, int>(INF, -1); 
        //完全に被覆されてるときは自分の値を返す
        if(a <= l && r <= b) return pair<int, int>(node[k], index[k]);
        //交差しているときは子に再帰して、帰ってきた値のモノイド演算を返す
        pair<int, int> pl = getmin(a, b, 2*k+1, l, (l+r)/2);
        pair<int, int> pr = getmin(a, b, 2*k+2, (l+r)/2, r);
        int minv = min(pl.first, pr.first);
        if (minv == pl.first) {
            return pl;
        } else {
            return pr;
        } 
    }
};

int main () {

    int n,m; cin >>n>>m;
    vector<P> pair(n);
    vector<int> vals(n);
    for (int i = 0; i < n; i++) {
        int a,b; cin >>a>>b;
        pair[i].first = a;
        pair[i].second = b;
    }
    sort(pair.begin(), pair.end());
    for (int i = 0; i < n; i++) {
        vals[i] = -pair[i].second;
    }

    SegmentTree tre(vals);

    int ans = 0;
    for (int i = 1; i <= m; i++) {
        int ok = -1;
        int ng = pair.size();
        while (abs(ok - ng) > 1) {
            int m = (ok+ng)/2;
            if (pair[m].first <= i) {
                ok = m;
            } else {
                ng = m;
            } 
        }
        if (ok != -1) {
            P res = tre.getmin(0, ok+1);
            if (res.first <= 0) {
                tre.update(res.second, 1);
                ans += -res.first;
            } 
        } 
    }

    cout << ans << endl;

    return 0;
}





Measured memory_bytes: 3840