#include <bits/stdc++.h>
using namespace std;
const int iinf = 1e9 + 7;
const long long linf = 1ll << 60;
const double dinf = 1e60;
template <typename T>
inline void scf(T &x) {
  bool f = 0;
  x = 0;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-') c = getchar();
  if (c == '-') {
    f = 1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  if (f) x = -x;
  return;
}
template <typename T1, typename T2>
void scf(T1 &x, T2 &y) {
  scf(x);
  return scf(y);
}
template <typename T1, typename T2, typename T3>
void scf(T1 &x, T2 &y, T3 &z) {
  scf(x);
  scf(y);
  return scf(z);
}
template <typename T1, typename T2, typename T3, typename T4>
void scf(T1 &x, T2 &y, T3 &z, T4 &w) {
  scf(x);
  scf(y);
  scf(z);
  return scf(w);
}
inline char mygetchar() {
  char c = getchar();
  while (c == ' ' || c == '\n') c = getchar();
  return c;
}
template <typename T>
void chkmax(T &x, const T &y) {
  if (y > x) x = y;
  return;
}
template <typename T>
void chkmin(T &x, const T &y) {
  if (y < x) x = y;
  return;
}
void TZL();
void RANK1();
int main() {
  TZL();
  RANK1();
  return 0;
}
const int N = 1e4 + 20;
struct edge {
  int to, cap, rev;
  edge() {}
  edge(int T, int C, int R) : to(T), cap(C), rev(R) {}
};
int n, S, T, tot;
vector<edge> g[N * 10];
vector<pair<pair<int, int>, int> > qo, qc;
int imp[N], dst[N * 10], iter[N * 10], fuck[N];
void add_edge(int from, int to, int cap) {
  edge a, b;
  a = edge(to, cap, (int)g[to].size());
  b = edge(from, 0, (int)g[from].size());
  g[from].push_back(a);
  g[to].push_back(b);
  return;
}
bool bfs() {
  static int q[N * 10];
  int fnt, rar;
  fnt = rar = 0;
  memset((dst), (-1), sizeof((dst)));
  dst[S] = 0;
  q[rar++] = S;
  while (fnt != rar) {
    int u = q[fnt++];
    for (auto e : g[u])
      if (e.cap && !~dst[e.to]) dst[e.to] = dst[u] + 1, q[rar++] = e.to;
  }
  return ~dst[T];
}
int dfs(int u = S, int f = iinf) {
  if (u == T) return f;
  for (int &i = iter[u]; i < (int)g[u].size(); ++i) {
    edge &e = g[u][i];
    if (e.cap && dst[e.to] > dst[u]) {
      int F = dfs(e.to, min(f, e.cap));
      if (F) {
        e.cap -= F;
        g[e.to][e.rev].cap += F;
        return F;
      }
    }
  }
  return 0;
}
struct node {
  node *l, *r;
  int id;
  node(int T = 0) : id(T) { l = r = 0; }
  void pull(bool dir) {
    if (dir)
      add_edge(id, l->id, iinf), add_edge(id, r->id, iinf);
    else
      add_edge(l->id, id, iinf), add_edge(r->id, id, iinf);
    return;
  }
} * rs, *rt;
void build(node *&cur, int l, int r, bool dir) {
  cur = new node((++tot));
  if (l == r) {
    if (dir)
      add_edge(tot, T, 1);
    else
      add_edge(S, tot, 1);
    return;
  }
  int mid = l + r >> 1;
  build(cur->l, l, mid, dir);
  build(cur->r, mid + 1, r, dir);
  cur->pull(dir);
  return;
}
void Link(node *cur, int a, int b, int to, bool dir, int l = 1, int r = n) {
  if (a == l && b == r) {
    if (!dir)
      add_edge(cur->id, to, iinf);
    else
      add_edge(to, cur->id, iinf);
    return;
  }
  int mid = l + r >> 1;
  if (a > mid) return Link(cur->r, a, b, to, dir, mid + 1, r);
  if (b <= mid) return Link(cur->l, a, b, to, dir, l, mid);
  return Link(cur->l, a, mid, to, dir, l, mid),
         Link(cur->r, mid + 1, b, to, dir, mid + 1, r);
}
void OPN(int l, int r, int y) {
  for (int i = (l), _end_ = (r); i <= _end_; ++i) {
    if (!fuck[i]) imp[i] = y;
    ++fuck[i];
  }
  return;
}
void CLS(int l, int r, int y) {
  for (int i = (l), _end_ = (r); i <= _end_; ++i) {
    int j = i;
    while (j <= r && fuck[j] == fuck[i] && imp[j] == imp[i]) ++j;
    --j;
    if (fuck[i] == 1) {
      int p = (++tot), q = (++tot);
      Link(rs, i, j, p, 0);
      Link(rt, imp[i], y, q, 1);
      add_edge(p, q, iinf);
    }
    for (int k = (i), _end_ = (j); k <= _end_; ++k) --fuck[k];
    i = j;
  }
  return;
}
void TZL() {
  scf(n);
  S = 0;
  T = 1;
  tot = 1;
  build(rs, 1, n, 0);
  build(rt, 1, n, 1);
  int q_n;
  scf(q_n);
  while (q_n--) {
    int x1, y1, x2, y2;
    scf(x1, y1, x2, y2);
    qc.push_back({{x1, x2}, y1 - 1});
    qo.push_back({{x1, x2}, y2 + 1});
  }
  qo.push_back({{1, n}, 1});
  qc.push_back({{1, n}, n});
  sort(qo.begin(), qo.end(),
       [&](pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) {
         return a.second < b.second;
       });
  sort(qc.begin(), qc.end(),
       [&](pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) {
         return a.second < b.second;
       });
  int i = 0, j = 0;
  while (i < (int)qo.size() || j < (int)qc.size()) {
    if (i == (int)qo.size() ||
        j != (int)qc.size() && qc[j].second < qo[i].second)
      CLS(qc[j].first.first, qc[j].first.second, qc[j].second), ++j;
    else
      OPN(qo[i].first.first, qo[i].first.second, qo[i].second), ++i;
  }
  return;
}
void RANK1() {
  int ans = 0;
  while (bfs()) {
    memset((iter), (0), sizeof((iter)));
    for (int f = dfs(); f; f = dfs()) ans += f;
  }
  printf("%d\n", ans);
  return;
}
