#include <bits/stdc++.h>
using namespace std;
const int MAX_INT = 2147483647;
const double PI = atan(1) * 4;
const int DX_KNIGHT[] = {2, 1, -1, -2, -2, -1, 1, 2};
const int DY_KNIGHT[] = {1, 2, 2, 1, -1, -2, -2, -1};
const int DX4[] = {1, 0, -1, 0};
const int DY4[] = {0, 1, 0, -1};
const int DX8[] = {1, 1, 1, 0, -1, -1, -1, 0};
const int DY8[] = {-1, 0, 1, 1, 1, 0, -1, -1};
template <typename T>
T minim(T &was, T cand) {
  return was = min(was, cand);
}
template <typename T>
T maxim(T &was, T cand) {
  return was = max(was, cand);
}
bool isValidCell(int r, int c, int n, int m) {
  return r >= 0 && c >= 0 && r < n && c < m;
}
template <typename T, typename U>
void decreaseByOne(vector<pair<T, U>> &v) {
  for (auto &p : v) {
    p.first--;
    p.second--;
  }
}
class Input {
 public:
  enum ErrorType { OK, END_OF_FILE, UNEXPECTED_SYMBOL, INVALID_CALL };

 private:
  istream &in;
  bool exhausted = false;
  ErrorType error = OK;
  int get();
  template <typename T>
  T readInteger();
  int skipWhitespace();

 public:
  Input(istream &in);
  int readInt();
  long long readLong();
  string readString();
  vector<int> readIntArray(int size);
  template <typename T>
  T readType();
  template <typename T, typename U>
  pair<T, U> readType();
  template <typename T>
  vector<T> readArray(int size);
  template <typename T, typename U>
  vector<pair<T, U>> readArray(int size);
  template <typename T1, typename T2>
  tuple<vector<T1>, vector<T2>> readArrays(int size);
  template <typename T1, typename T2, typename T3>
  tuple<vector<T1>, vector<T2>, vector<T3>> readArrays(int size);
  template <typename T1, typename T2, typename T3, typename T4>
  tuple<vector<T1>, vector<T2>, vector<T3>, vector<T4>> readArrays(int size);
  template <typename T1, typename T2, typename T3, typename T4, typename T5>
  tuple<vector<T1>, vector<T2>, vector<T3>, vector<T4>, vector<T5>> readArrays(
      int size);
  template <typename T>
  vector<vector<T>> readTable(int rows, int cols);
  string readLine();
  double readDouble();
  bool isExhausted() { return exhausted; }
};
inline bool isWhitespace(int c) { return isspace(c) || c == EOF; }
int Input::skipWhitespace() {
  int c;
  do {
    c = get();
    if (exhausted) {
      error = END_OF_FILE;
      return c;
    }
  } while (isWhitespace(c));
  return c;
}
Input::Input(std::istream &in) : in(in) {}
inline int Input::get() {
  int result = in.get();
  if (result == EOF) {
    exhausted = true;
  }
  return result;
}
template <typename T>
T Input::readType() {
  error = INVALID_CALL;
  return nullptr;
}
template <>
double Input::readType() {
  error = OK;
  int c = skipWhitespace();
  if (error != OK) {
    return 0;
  }
  int sgn = 1;
  if (c == '-') {
    sgn = -1;
    c = get();
  }
  double res = 0;
  do {
    if (!isdigit(c)) {
      error = UNEXPECTED_SYMBOL;
      return 0;
    }
    res *= 10;
    res += c - '0';
    c = get();
  } while (!isWhitespace(c) && c != '.');
  if (c == '.') {
    vector<int> digits;
    c = get();
    do {
      if (!isdigit(c)) {
        error = UNEXPECTED_SYMBOL;
        return 0;
      }
      digits.push_back(c - '0');
      c = get();
    } while (!isWhitespace(c));
    double add = 0;
    for (int i = int(digits.size()) - 1; i >= 0; i--) {
      add += digits[i];
      add /= 10;
    }
    res += add;
  }
  return res;
}
template <typename T>
T Input::readInteger() {
  error = OK;
  int c = skipWhitespace();
  if (error != OK) {
    return 0;
  }
  int sgn = 1;
  if (c == '-') {
    sgn = -1;
    c = get();
  }
  T res = 0;
  do {
    if (!isdigit(c)) {
      error = UNEXPECTED_SYMBOL;
      return 0;
    }
    res *= 10;
    res += c - '0';
    c = get();
  } while (!isWhitespace(c));
  return res * sgn;
}
template <>
int Input::readType() {
  return readInteger<int>();
}
template <>
long long Input::readType() {
  return readInteger<long long>();
}
template <>
char Input::readType() {
  error = OK;
  int c = skipWhitespace();
  if (error != OK) {
    return 0;
  }
  return c;
}
template <>
string Input::readType() {
  error = OK;
  int c = skipWhitespace();
  if (error != OK) {
    return "";
  }
  vector<char> res;
  do {
    if (error != OK) {
      return "";
    }
    res.push_back(c);
  } while (!isWhitespace(c = get()));
  return string(res.begin(), res.end());
}
inline int Input::readInt() { return readType<int>(); }
inline long long Input::readLong() { return readType<long long>(); }
template <typename T>
vector<T> Input::readArray(int size) {
  vector<T> res;
  res.reserve(size);
  for (int i = 0; i < size; i++) {
    res.push_back(readType<T>());
    if (error != OK) {
      res.clear();
      return res;
    }
  }
  return res;
}
template <typename U, typename V>
pair<U, V> Input::readType() {
  U first = readType<U>();
  V second = readType<V>();
  return make_pair(first, second);
}
template <typename U, typename V>
vector<pair<U, V>> Input::readArray(int size) {
  vector<pair<U, V>> res;
  res.reserve(size);
  for (int i = 0; i < size; i++) {
    res.push_back(readType<U, V>());
    if (error != OK) {
      res.clear();
      return res;
    }
  }
  return res;
}
vector<int> Input::readIntArray(int size) { return readArray<int>(size); }
template <typename T1, typename T2>
tuple<vector<T1>, vector<T2>> Input::readArrays(int size) {
  vector<T1> v1;
  vector<T2> v2;
  v1.reserve(size);
  v2.reserve(size);
  for (int i = 0; i < size; ++i) {
    v1.push_back(readType<T1>());
    v2.push_back(readType<T2>());
  }
  return make_tuple(v1, v2);
}
string Input::readString() { return readType<string>(); }
template <typename T>
vector<vector<T>> Input::readTable(int rows, int cols) {
  vector<vector<T>> result;
  result.reserve(rows);
  for (int i = 0; i < rows; ++i) {
    result.push_back(readArray<T>(cols));
  }
  return result;
}
string Input::readLine() {
  error = OK;
  int c = skipWhitespace();
  if (error != OK) {
    return "";
  }
  int length = 0;
  vector<char> res;
  do {
    if (error != OK) {
      return "";
    }
    res.push_back(c);
    if (!isWhitespace(c)) {
      length = res.size();
    }
    c = get();
  } while (c != '\n' && c != '\r' && c != EOF);
  return string(res.begin(), res.begin() + length);
}
double Input::readDouble() { return readType<double>(); }
template <typename T1, typename T2, typename T3>
tuple<vector<T1>, vector<T2>, vector<T3>> Input::readArrays(int size) {
  vector<T1> v1;
  vector<T2> v2;
  vector<T3> v3;
  v1.reserve(size);
  v2.reserve(size);
  v3.reserve(size);
  for (int i = 0; i < size; ++i) {
    v1.push_back(readType<T1>());
    v2.push_back(readType<T2>());
    v3.push_back(readType<T3>());
  }
  return make_tuple(v1, v2, v3);
}
template <typename T1, typename T2, typename T3, typename T4>
tuple<vector<T1>, vector<T2>, vector<T3>, vector<T4>> Input::readArrays(
    int size) {
  vector<T1> v1;
  vector<T2> v2;
  vector<T3> v3;
  vector<T4> v4;
  v1.reserve(size);
  v2.reserve(size);
  v3.reserve(size);
  v4.reserve(size);
  for (int i = 0; i < size; ++i) {
    v1.push_back(readType<T1>());
    v2.push_back(readType<T2>());
    v3.push_back(readType<T3>());
    v4.push_back(readType<T4>());
  }
  return make_tuple(v1, v2, v3, v4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
tuple<vector<T1>, vector<T2>, vector<T3>, vector<T4>, vector<T5>>
Input::readArrays(int size) {
  vector<T1> v1;
  vector<T2> v2;
  vector<T3> v3;
  vector<T4> v4;
  vector<T5> v5;
  v1.reserve(size);
  v2.reserve(size);
  v3.reserve(size);
  v4.reserve(size);
  v5.reserve(size);
  for (int i = 0; i < size; ++i) {
    v1.push_back(readType<T1>());
    v2.push_back(readType<T2>());
    v3.push_back(readType<T3>());
    v4.push_back(readType<T4>());
    v5.push_back(readType<T5>());
  }
  return make_tuple(v1, v2, v3, v4, v5);
}
class Output {
 private:
  ostream &out;
  template <typename T>
  void printSingle(const T &value);
  template <typename T>
  void printSingle(const vector<T> &value);
  template <typename T, typename U>
  void printSingle(const pair<T, U> &value);

 public:
  Output(ostream &out);
  void print();
  template <typename T, typename... Targs>
  void print(const T &first, const Targs... args);
  template <typename... Targs>
  void printLine(const Targs... args);
};
Output::Output(ostream &out) : out(out) { out << setprecision(12); }
void Output::print() {}
template <typename T, typename... Targs>
void Output::print(const T &first, const Targs... args) {
  printSingle(first);
  if (sizeof...(args) != 0) {
    out << ' ';
    print(args...);
  }
}
template <typename T>
void Output::printSingle(const T &value) {
  out << value;
}
template <typename... Targs>
void Output::printLine(const Targs... args) {
  print(args...);
  out << '\n';
}
template <typename T>
void Output::printSingle(const vector<T> &array) {
  unsigned int size = array.size();
  for (int i = 0; i < size; ++i) {
    out << array[i];
    if (i + 1 != size) {
      out << ' ';
    }
  }
}
template <typename T, typename U>
void Output::printSingle(const pair<T, U> &value) {
  out << value.first << ' ' << value.second;
}
template <typename W, typename C>
class WeightedFlowEdge {
 private:
  WeightedFlowEdge<W, C> *reverseEdge;

 public:
  const int from;
  const int to;
  W weight;
  C capacity;
  int id;
  WeightedFlowEdge(int from, int to, W weight, C capacity)
      : from(from), to(to), weight(weight), capacity(capacity) {
    reverseEdge = new WeightedFlowEdge(this);
  }
  WeightedFlowEdge<W, C> *transposed() { return nullptr; }
  WeightedFlowEdge<W, C> *reverse() { return reverseEdge; }
  void push(C flow) {
    capacity -= flow;
    reverseEdge->capacity += flow;
  }
  C flow() const { return reverseEdge->capacity; }

 private:
  WeightedFlowEdge(WeightedFlowEdge<W, C> *reverse)
      : from(reverse->to),
        to(reverse->from),
        weight(-reverse->weight),
        capacity(0) {
    reverseEdge = reverse;
  }
};
template <typename C>
class FlowEdge {
 private:
  FlowEdge<C> *reverseEdge;

 public:
  const int from;
  const int to;
  C capacity;
  int id;
  FlowEdge(int from, int to, C capacity)
      : from(from), to(to), capacity(capacity) {
    reverseEdge = new FlowEdge(this);
  }
  FlowEdge<C> *transposed() { return nullptr; }
  FlowEdge<C> *reverse() { return reverseEdge; }
  void push(C flow) {
    capacity -= flow;
    reverseEdge->capacity += flow;
  }
  C flow() const { return reverseEdge->capacity; }

 private:
  FlowEdge(FlowEdge<C> *reverse)
      : from(reverse->to), to(reverse->from), capacity(0) {
    reverseEdge = reverse;
  }
};
template <typename W>
class WeightedEdge {
 public:
  const int from;
  const int to;
  W weight;
  int id;
  WeightedEdge(int from, int to, W weight)
      : from(from), to(to), weight(weight) {}
  WeightedEdge<W> *transposed() { return nullptr; }
  WeightedEdge<W> *reverse() { return nullptr; }
};
template <typename W>
class BidirectionalWeightedEdge {
 private:
  BidirectionalWeightedEdge<W> *transposedEdge;

 public:
  const int from;
  const int to;
  W weight;
  int id;
  BidirectionalWeightedEdge(int from, int to, W weight)
      : from(from), to(to), weight(weight) {
    transposedEdge = new BidirectionalWeightedEdge(this);
  }
  BidirectionalWeightedEdge<W> *transposed() { return transposedEdge; }
  BidirectionalWeightedEdge<W> *reverse() { return nullptr; }

 private:
  BidirectionalWeightedEdge(BidirectionalWeightedEdge<W> *transposed)
      : from(transposed->to), to(transposed->from), weight(transposed->weight) {
    transposedEdge = transposed;
  }
};
class SimpleEdge {
 public:
  const int from;
  const int to;
  int id;
  SimpleEdge(int from, int to) : from(from), to(to) {}
  SimpleEdge *transposed() { return nullptr; }
  SimpleEdge *reverse() { return nullptr; }
};
class BidirectionalEdge {
 private:
  BidirectionalEdge *transposedEdge;

 public:
  const int from;
  const int to;
  int id;
  BidirectionalEdge(int from, int to) : from(from), to(to) {
    transposedEdge = new BidirectionalEdge(this);
  }
  BidirectionalEdge *transposed() { return transposedEdge; }
  BidirectionalEdge *reverse() { return nullptr; }

 private:
  BidirectionalEdge(BidirectionalEdge *transposed)
      : from(transposed->to), to(transposed->from) {
    transposedEdge = transposed;
  }
};
template <class Edge>
class Graph {
 public:
  int vertexCount;
  int edgeCount = 0;
  vector<vector<Edge *>> edges;
  Graph(int vertexCount) : vertexCount(vertexCount) {
    edges.resize(vertexCount);
  }
  void addEdge(Edge *edge) {
    edge->id = edgeCount;
    edges[edge->from].push_back(edge);
    if (edge->reverse() != nullptr) {
      edge->reverse()->id = edgeCount;
      edges[edge->reverse()->from].push_back(edge->reverse());
    }
    if (edge->transposed() != nullptr) {
      edges[edge->transposed()->from].push_back(edge->transposed());
      edge->transposed()->id = edgeCount;
      if (edge->transposed()->reverse() != nullptr) {
        edges[edge->transposed()->reverse()->from].push_back(
            edge->transposed()->reverse());
        edge->transposed()->reverse()->id = edgeCount;
      }
    }
    edgeCount++;
  }
};
template <class Edge, typename C>
class MaxFlow {
 private:
  Graph<Edge> *graph;
  int source;
  int destination;
  queue<int> q;
  vector<int> dist;
  vector<int> nextEdge;
  C inf;
  void edgeDistances() {
    fill((dist).begin(), (dist).end(), -1);
    dist[source] = 0;
    q.push(source);
    while (!q.empty()) {
      int current = q.front();
      q.pop();
      for (auto edge : graph->edges[current]) {
        if (edge->capacity != 0) {
          int next = edge->to;
          if (dist[next] == -1) {
            dist[next] = dist[current] + 1;
            q.push(next);
          }
        }
      }
    }
  }
  C dinicImpl(int source, C flow) {
    if (source == destination) {
      return flow;
    }
    if (flow == 0 || dist[source] == dist[destination]) {
      return 0;
    }
    C totalPushed = 0;
    while (nextEdge[source] < graph->edges[source].size()) {
      auto edge = graph->edges[source][nextEdge[source]];
      if (edge->capacity != 0 && dist[edge->to] == dist[source] + 1) {
        C pushed = dinicImpl(edge->to, min(flow, edge->capacity));
        if (pushed != 0) {
          edge->push(pushed);
          flow -= pushed;
          totalPushed += pushed;
          if (flow == 0) {
            return totalPushed;
          }
        }
      }
      nextEdge[source]++;
    }
    return totalPushed;
  }

 public:
  MaxFlow(Graph<Edge> &graph, int source, int destination)
      : graph(&graph), source(source), destination(destination) {
    dist = vector<int>(graph.vertexCount);
    nextEdge = vector<int>(graph.vertexCount);
    inf = numeric_limits<C>().max();
  }
  C dinic() {
    C totalFlow = 0;
    while (true) {
      edgeDistances();
      if (dist[destination] == -1) {
        break;
      }
      fill(nextEdge.begin(), nextEdge.end(), 0);
      totalFlow += dinicImpl(source, inf);
    }
    return totalFlow;
  }
};
template <class Edge, typename C>
C dinic(Graph<Edge> &graph, int source, int destination) {
  return MaxFlow<Edge, C>(graph, source, destination).dinic();
}
class task {
 public:
  void solve(istream &inp, ostream &outp) {
    Input in(inp);
    Output out(outp);
    int n = in.readInt();
    int m = in.readInt();
    vector<int> l;
    vector<int> r;
    tie(l, r) = in.readArrays<int, int>(n);
    Graph<FlowEdge<int>> graph(3 * m + n + 2);
    int source = 3 * m + n;
    int sink = source + 1;
    for (int i = 0; i < n; i++) {
      graph.addEdge(new FlowEdge<int>(source, 3 * m + i, 1));
      if (l[i] > 0) {
        graph.addEdge(new FlowEdge<int>(3 * m + i, l[i] - 1, 1));
      }
      if (r[i] <= m) {
        graph.addEdge(new FlowEdge<int>(3 * m + i, m + r[i] - 1, 1));
      }
    }
    for (int i = 1; i < m; i++) {
      graph.addEdge(new FlowEdge<int>(i, i - 1, n));
      graph.addEdge(new FlowEdge<int>(i - 1 + m, i + m, n));
    }
    for (int i = 0; i < m; i++) {
      graph.addEdge(new FlowEdge<int>(i, 2 * m + i, 1));
      graph.addEdge(new FlowEdge<int>(i + m, 2 * m + i, 1));
      graph.addEdge(new FlowEdge<int>(2 * m + i, sink, 1));
    }
    out.printLine(n - dinic<FlowEdge<int>, int>(graph, source, sink));
  }
};
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  task solver;
  std::istream &in(std::cin);
  std::ostream &out(std::cout);
  solver.solve(in, out);
  return 0;
}
