/**
 * Author   : rama_pang
 * Problem  : https://arc076.contest.atcoder.jp/tasks/arc076_d
 * Time     : O(n log n)
 * Memory   : O(n)
 * 
 * Solution :
 * 
 * Rough proof, that N - (S - T) = Maximum Matching, for
 * a maximum value of (S - T).
 * 
 * First, consider a bipartite graph with |A| <= |B|.
 * 
 * Consider a maximum matching. Let S be vertices matched in A
 * and T in B. S' and T' are complements of S and T.
 * 
 * Clearly if we pick all vertices in S', then each neighbour of
 * it are already matched.
 * 
 * We denote U the union of S', its neighbours, and the neighbours'
 * matches. U' is a perfect matching.
 * 
 * Suppose we want to maximize P and Q, such that P - Q is maximal.
 * Then since U' is a perffect matching, it makes no sense to include
 * it. Then, we can see S - (P - Q) = Maximum Matching.
 * 
 * 
 * The problem is now reduced to finding the maximum (S - T), to find
 * the maximum matching.
 * 
 * Assume we have a subset {(L1, R1), (L2, R2), ..., (Lk, Rk)}.
 * Then the value of (S - T) is k - min(max(L) + max(M + 1 - R), M).
 * 
 * We want to maximize:
 * k - min(max(L) + max(M + 1 - R), M).
 * Which is max(k - M, k - max(L) - max(M + 1 - R))
 * 
 * Sort the inputs by R, then we can fix current max(M + 1 - R) and find the maximum
 * value of k - max(L).
 * 
 * This can be done using a segment tree or BST. 
 * 
**/

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

mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());

struct TreapNode { // Multiset, can query max(index - val)
  int sz, prior, key;
  int val, ans, lazy;
  TreapNode *l, *r;

  TreapNode(int v, int k) {
    key = k;
    sz = 1, ans = val = v, lazy = 0;
    prior = rnd();
    l = r = nullptr;
  }
};

using tnode = TreapNode;
using pt = tnode*;

int sz(pt t) {
  return t != nullptr ? t->sz : 0;
}

int ans(pt t) {
  return t != nullptr ? t->ans : -1e9;
}

void upd(pt t) {
  if (t != nullptr) {
    t->sz = sz(t->l) + sz(t->r) + 1;
    t->ans = max({ans(t->l), ans(t->r), t->val});
  }
}

void push(pt t) {
  if (t == nullptr) {
    return;
  }
  if (t->l != nullptr) {
    t->l->val += t->lazy;
    t->l->ans += t->lazy;
    t->l->lazy += t->lazy;
  }
  if (t->r != nullptr) {
    t->r->val += t->lazy;
    t->r->ans += t->lazy;
    t->r->lazy += t->lazy;
  }
  t->lazy = 0;
}

void split(pt t, pt &l, pt &r, int key) {
  push(t);
  if (t == nullptr) {
    l = r = nullptr;
  } else if (t->key <= key) {
    split(t->r, t->r, r, key), l = t;
  } else {
    split(t->l, l, t->l, key), r = t;
  }
  upd(t);
}

void merge(pt &t, pt l, pt r) {
  push(l), push(r);
  if (l == nullptr || r == nullptr) {
    t = l == nullptr ? r : l;
  } else if (l->prior > r->prior) {
    merge(l->r, l->r, r), t = l;
  } else {
    merge(r->l, l, r->l), t = r;
  }
  upd(t);
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  int N, M;
  cin >> N >> M;

  vector<pair<int, int>> seg;
  for (int i = 0; i < N; i++) {
    int l, r;
    cin >> l >> r;
    seg.emplace_back(l, r);
  }

  sort(begin(seg), end(seg), [&](pair<int, int> &a, pair<int, int> &b) {
    return a.second > b.second;
  });

  int res = 0; // maximum difference
  multiset<int> L;
  
  pt treap = nullptr;


  for (int i = 0; i < N; i++) {
    int r = M + 1 - seg[i].second;
    
    pt tl, tr, n;
    split(treap, tl, tr, seg[i].first);
    n = new tnode(sz(tl) + 1 - seg[i].first, seg[i].first); // insert new node

    if (tr != nullptr) { // indexes are added by 1
      tr->ans += 1;
      tr->val += 1;
      tr->lazy += 1;
    }

    merge(treap, tl, n);
    merge(treap, treap, tr);
    res = max(res, ans(treap) - r);
  }

  res = max(res, N - M);
  cout << res << "\n";

  return 0;
}


Measured memory_bytes: 11248