Problem:
Score : 1000 points

Problem Statement

There are M chairs arranged in a line. The coordinate of the i-th chair (1 ≤ i ≤ M) is i.

N people of the Takahashi clan played too much games, and they are all suffering from backaches. They need to sit in chairs and rest, but they are particular about which chairs they sit in. Specifically, the i-th person wishes to sit in a chair whose coordinate is not greater than L_i, or not less than R_i. Naturally, only one person can sit in the same chair.

It may not be possible for all of them to sit in their favorite chairs, if nothing is done.
Aoki, who cares for the health of the people of the Takahashi clan, decides to provide additional chairs so that all of them can sit in chairs at their favorite positions.

Additional chairs can be placed at arbitrary real coordinates. Find the minimum required number of additional chairs.

Constraints

1 ≤ N,M ≤ 2 × 10^5

0 ≤ L_i < R_i ≤ M + 1(1 ≤ i ≤ N)

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M
L_1 R_1
:
L_N R_N

Output

Print the minimum required number of additional chairs.

Sample Input 1

4 4
0 3
2 3
1 3
3 4

Sample Output 1

0

The four people can sit in chairs at the coordinates 3, 2, 1 and 4, respectively, and no more chair is needed.

Sample Input 2

7 6
0 7
1 5
3 6
2 7
1 6
2 6
3 7

Sample Output 2

2

If we place additional chairs at the coordinates 0 and 2.5, the seven people can sit at coordinates 0, 5, 3, 2, 6, 1 and 2.5, respectively.

Sample Input 3

3 1
1 2
1 2
1 2

Sample Output 3

2

Sample Input 4

6 6
1 6
1 6
1 5
1 5
2 6
2 6

Sample Output 4

2

Solution in C++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Egor Kulikov
 */

#include <iostream>
#include <fstream>

#ifndef JHELPER_EXAMPLE_PROJECT_INPUT_H
#define JHELPER_EXAMPLE_PROJECT_INPUT_H

#ifndef JHELPER_EXAMPLE_PROJECT_GENERAL_H
#define JHELPER_EXAMPLE_PROJECT_GENERAL_H

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;

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--;
    }
}

#endif //JHELPER_EXAMPLE_PROJECT_GENERAL_H


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();

    ll 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 == '.') {
        vi 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<>
ll Input::readType() {
    return readInteger<ll>();
}

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 ll Input::readLong() {
    return readType<ll>();
}

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);
}

#endif //JHELPER_EXAMPLE_PROJECT_INPUT_H

//
// Created by egor on 31.10.2019.
//

#ifndef JHELPER_EXAMPLE_PROJECT_OUTPUT_H
#define JHELPER_EXAMPLE_PROJECT_OUTPUT_H


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;
}

#endif //JHELPER_EXAMPLE_PROJECT_OUTPUT_H

//
// Created by egor on 04.11.2019.
//

#ifndef JHELPER_EXAMPLE_PROJECT_GRAPH_H
#define JHELPER_EXAMPLE_PROJECT_GRAPH_H


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++;
    }
};

typedef FlowEdge<ll> LongFlowEdge;
typedef WeightedEdge<ll> LongWeightedEdge;
typedef FlowEdge<int> IntFlowEdge;
typedef WeightedEdge<int> IntWeightedEdge;
typedef BidirectionalWeightedEdge<ll> LongBiWeightedEdge;
typedef BidirectionalWeightedEdge<int> IntBiWeightedEdge;

#endif //JHELPER_EXAMPLE_PROJECT_GRAPH_H

//
// Created by kulikov on 11/7/2019.
//

#ifndef JHELPER_EXAMPLE_PROJECT_FLOW_H
#define JHELPER_EXAMPLE_PROJECT_FLOW_H


template<class Edge, typename C>
class MaxFlow {
private:
    Graph<Edge> *graph;
    int source;
    int destination;
    queue<int> q;
    vi dist;
    vi nextEdge;
    C inf;

    void edgeDistances() {
        fill(all(dist), -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 = vi(graph.vertexCount);
        nextEdge = vi(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();
}

#endif //JHELPER_EXAMPLE_PROJECT_FLOW_H


//#pragma comment(linker, "/STACK:200000000")

class task {
public:
    void solve(istream &inp, ostream &outp) {
        Input in(inp);
        Output out(outp);

        int n = in.readInt();
        int m = in.readInt();
        vi l;
        vi r;
        tie(l, r) = in.readArrays<int, int>(n);
        Graph<IntFlowEdge> graph(3 * m + n + 2);
        int source = 3 * m + n;
        int sink = source + 1;
        for (int i = 0; i < n; i++) {
            graph.addEdge(new IntFlowEdge(source, 3 * m + i, 1));
            if (l[i] > 0) {
                graph.addEdge(new IntFlowEdge(3 * m + i, l[i] - 1, 1));
            }
            if (r[i] <= m) {
                graph.addEdge(new IntFlowEdge(3 * m + i, m + r[i] - 1, 1));
            }
        }
        for (int i = 1; i < m; i++) {
            graph.addEdge(new IntFlowEdge(i, i - 1, n));
            graph.addEdge(new IntFlowEdge(i - 1 + m, i + m, n));
        }
        for (int i = 0; i < m; i++) {
            graph.addEdge(new IntFlowEdge(i, 2 * m + i, 1));
            graph.addEdge(new IntFlowEdge(i + m, 2 * m + i, 1));
            graph.addEdge(new IntFlowEdge(2 * m + i, sink, 1));
        }
        out.printLine(n - dinic<IntFlowEdge, 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;
}