#include <bits/stdc++.h>
using namespace std;
struct Dinic {
  static const int MXN = (int)2e6;
  struct Edge {
    int v, f, re;
  };
  int n, s, t, level[MXN];
  vector<Edge> E[MXN];
  void init(int _n, int _s, int _t) {
    n = _n;
    s = _s;
    t = _t;
  }
  void add_edge(int u, int v, int f) {
    E[u].push_back({v, f, (int)E[v].size()});
    E[v].push_back({u, 0, (int)E[u].size() - 1});
  }
  bool BFS() {
    for (int i = 0; i < n; i++) level[i] = -1;
    queue<int> que;
    que.push(s);
    level[s] = 0;
    while (!que.empty()) {
      int u = que.front();
      que.pop();
      for (auto &it : E[u]) {
        if (it.f > 0 && level[it.v] == -1) {
          level[it.v] = level[u] + 1;
          que.push(it.v);
        }
      }
    }
    return level[t] != -1;
  }
  int DFS(int u, int nf) {
    if (u == t) return nf;
    int res = 0;
    for (auto &it : E[u]) {
      if (it.f > 0 && level[it.v] == level[u] + 1) {
        int tf = DFS(it.v, min(nf, it.f));
        res += tf;
        nf -= tf;
        it.f -= tf;
        E[it.v][it.re].f += tf;
        if (nf == 0) return res;
      }
    }
    if (!res) level[u] = -1;
    return res;
  }
  int flow(int res = 0) {
    while (BFS()) res += DFS(s, 2147483647);
    return res;
  }
} flow;
struct Node {
  int l, r, y, v;
  bool operator<(const Node &rhs) const { return y < rhs.y; }
};
int n, q, s, t, tot;
vector<Node> seg;
namespace segtree {
static const int N = (int)1e4 + 5;
static const int inf = (int)1e9;
int id[N * 4], id2[N * 4], tag[N * 4];
void pull(int o, int lson, int rson) {
  id[o] = tot++;
  if (!tag[lson]) flow.add_edge(id[o], id[lson], inf);
  if (!tag[rson]) flow.add_edge(id[o], id[rson], inf);
}
void build1(int l, int r, int o = 0) {
  if (l + 1 == r) return void(id[o] = n + l);
  int mid = (l + r) >> 1, lson = o * 2 + 1, rson = o * 2 + 2;
  build1(l, mid, lson);
  build1(mid, r, rson);
  pull(o, lson, rson);
}
void build2(int l, int r, int o = 0) {
  if (l + 1 == r) return void(id2[o] = l);
  int mid = (l + r) >> 1, lson = o * 2 + 1, rson = o * 2 + 2;
  id2[o] = tot++;
  build2(l, mid, lson);
  build2(mid, r, rson);
  flow.add_edge(id2[lson], id2[o], inf);
  flow.add_edge(id2[rson], id2[o], inf);
}
void build(int l, int r) {
  build1(l, r);
  build2(l, r);
}
void modify1(int l, int r, int ql, int qr, int v, int o = 0) {
  if (ql <= l && r <= qr) return void(tag[o] += v);
  int mid = (l + r) >> 1, lson = o * 2 + 1, rson = o * 2 + 2;
  if (ql < mid) modify1(l, mid, ql, qr, v, lson);
  if (mid < qr) modify1(mid, r, ql, qr, v, rson);
  pull(o, lson, rson);
}
void modify2(int l, int r, int ql, int qr, int o = 0) {
  if (ql <= l && r <= qr) return void(flow.add_edge(id2[o], id[0], inf));
  int mid = (l + r) >> 1, lson = o * 2 + 1, rson = o * 2 + 2;
  if (ql < mid) modify2(l, mid, ql, qr, lson);
  if (mid < qr) modify2(mid, r, ql, qr, rson);
}
void modify(int l, int r, int ql1, int qr1, int v, int ql2, int qr2) {
  if (!tag[0] && ql2 < qr2) modify2(l, r, ql2, qr2);
  modify1(l, r, ql1, qr1, v);
}
}  // namespace segtree
void init() {
  cin >> n >> q;
  for (int i = 0; i < q; ++i) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    seg.push_back({x1, x2 + 1, y1, 1});
    seg.push_back({x1, x2 + 1, y2 + 1, -1});
  }
  sort(seg.begin(), seg.end());
}
void solve() {
  tot = 2 * n + 2, s = 0, t = 2 * n + 1;
  for (int i = 1; i <= n; ++i) {
    flow.add_edge(s, i, 1);
    flow.add_edge(i + n, t, 1);
  }
  segtree::build(1, n + 1);
  int preY = 1;
  for (auto [l, r, y, v] : seg) {
    segtree::modify(1, n + 1, l, r, v, preY, y);
    preY = y;
  }
  if (preY < n + 1) segtree::modify2(1, n + 1, preY, n + 1);
  flow.init(tot, s, t);
  cout << flow.flow() << '\n';
}
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  init();
  solve();
}
