#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
ostream& operator<<(ostream& os, const pair<A, B>& x) {
  return os << "(" << x.first << "," << x.second << ")";
}
const int INF = 1e8;
template <typename T>
struct Dinic {
  static const T eps = 1e-9;
  int n, src, sink;
  struct Edge {
    int from, to;
    T f, cap;
  };
  vector<int> dist, Q, work;
  vector<Edge> edges;
  vector<vector<int>> G;
  Dinic(int _n) : n(_n) {
    G.resize(n);
    dist.resize(n);
    Q.resize(n);
    work.resize(n);
  }
  int addEdge(int s, int t, T forwardCap, T backwardCap = 0) {
    int id = edges.size();
    G[s].push_back(id);
    edges.push_back({s, t, 0, forwardCap});
    G[t].push_back(id + 1);
    edges.push_back({t, s, 0, backwardCap});
    return id;
  }
  bool dinicBfs() {
    fill(dist.begin(), dist.begin() + n, -1);
    dist[src] = 0;
    int qt = 0;
    Q[qt++] = src;
    for (int qh = 0; qh < qt; ++qh) {
      int u = Q[qh];
      for (int eid : G[u]) {
        Edge& e = edges[eid];
        int v = e.to;
        if (dist[v] < 0 && e.cap - e.f > eps) {
          dist[v] = dist[u] + 1;
          Q[qt++] = v;
        }
      }
    }
    return dist[sink] >= 0;
  }
  T dinicDfs(int u, T f) {
    if (u == sink) return f;
    for (int& i = work[u]; i < G[u].size(); ++i) {
      int eid = G[u][i];
      Edge& e = edges[eid];
      if (e.cap <= e.f) continue;
      int v = e.to;
      if (dist[v] == dist[u] + 1) {
        T df = dinicDfs(v, min(f, e.cap - e.f));
        if (df > 0) {
          e.f += df;
          edges[eid ^ 1].f -= df;
          return df;
        }
      }
    }
    return 0;
  }
  T maxFlow() {
    assert(src != -1 && sink != -1);
    T result = 0;
    while (dinicBfs()) {
      fill(work.begin(), work.begin() + n, 0);
      for (;;) {
        T delta = dinicDfs(src, numeric_limits<T>::max());
        if (delta <= eps) break;
        result += delta;
      }
    }
    return result;
  }
  vector<bool> minCut() {
    maxFlow();
    vector<bool> ret(n);
    for (int i = 0; i < n; ++i) ret[i] = dist[i] >= 0;
    return ret;
  }
  int na, nb;
  vector<int> matcha, matchb;
  Dinic(int _na, int _nb) : Dinic(_na + _nb + 2) {
    na = _na;
    nb = _nb;
    src = n - 2;
    sink = n - 1;
    for (int i = 0; i < na; ++i) addEdge(src, i, 1);
    for (int i = 0; i < nb; ++i) addEdge(na + i, sink, 1);
  }
  int addMatchEdge(int s, int t) { return addEdge(s, t + na, 1); }
  int maxMatching() {
    int ret = maxFlow();
    matcha.resize(na);
    matchb.resize(nb);
    for (int i = 0; i < na; ++i) {
      for (int eid : G[i]) {
        auto& e = edges[eid];
        if (e.to != src && e.f == 1) {
          matcha[i] = e.to - na;
          matchb[e.to - na] = i;
        }
      }
    }
    return ret;
  }
};
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  Dinic<int> g(n + m + m + 3);
  g.src = g.n - 2;
  g.sink = g.n - 1;
  for (int i = 0; i < n; ++i) {
    int l, r;
    scanf("%d%d", &l, &r);
    r = m + 1 - r;
    if (l >= 1) {
      g.addEdge(i, n + l, 1);
    }
    if (r >= 1) {
      g.addEdge(i, n + m + r, 1);
    }
    g.addEdge(g.src, i, 1);
  }
  for (int i = 1; i <= m; ++i) {
    if (i > 1) g.addEdge(n + i, n + i - 1, INF);
    g.addEdge(n + i, g.sink, 1);
    if (i > 1) g.addEdge(n + m + i, n + m + i - 1, INF);
    g.addEdge(n + m + i, g.sink, 1);
  }
  int ans = g.maxFlow();
  printf("%d\n", n - ans);
}
