#include <bits/stdc++.h>
using namespace std;
const int N = 10010, M = 600000, inf = 1e9;
struct st {
  int x, l, r, f;
} c[N << 1];
struct E {
  int v, nxt, w;
} e[M * 5];
int n, m, p, S, T, r1, r2, cnt, cc = 1, ls[N << 3], rs[N << 3], a[N], hd[M],
                                dis[M], q[M], iter[M];
inline void add(int u, int v, int w) {
  e[++cc] = (E){v, hd[u], w};
  hd[u] = cc;
  e[++cc] = (E){u, hd[v], 0};
  hd[v] = cc;
}
void build(int &x, int y, int l, int r, int d) {
  x = ++cnt;
  if (y) {
    if (!d)
      add(x, y, inf);
    else
      add(y, x, inf);
  }
  if (l == r) return;
  int mid = l + r >> 1;
  build(ls[x], x, l, mid, d);
  build(rs[x], x, mid + 1, r, d);
}
void build2(int x, int l, int r, int y) {
  if (l == r) {
    if (!y)
      add(0, x, 1);
    else
      add(x, T, 1);
    return;
  }
  int mid = l + r >> 1;
  build2(ls[x], l, mid, y);
  build2(rs[x], mid + 1, r, y);
}
bool cmp(st a, st b) { return a.x == b.x ? a.f > b.f : a.x < b.x; }
inline void qry(int x, int l, int r, int tl, int tr, int y, int d) {
  if (!x || l > tr || r < tl) return;
  if (tl <= l && r <= tr) {
    if (!d)
      add(x, y, inf);
    else
      add(y, x, inf);
    return;
  }
  int mid = l + r >> 1;
  qry(ls[x], l, mid, tl, tr, y, d);
  qry(rs[x], mid + 1, r, tl, tr, y, d);
}
inline void ins(int x, int l, int r) {
  int p = -1, lst = -1, y;
  for (int i = l; i <= r + 1; i++) {
    if (i <= r) y = a[i] + 1, a[i] = -1;
    if (y != lst || i == r + 1) {
      if (~p) {
        int t = ++cnt;
        qry(r1, 1, n, p, i - 1, t, 0);
        qry(r2, 1, n, lst, x, t, 1);
      }
      p = i;
      lst = y;
    }
  }
}
inline void upd(int x, int l, int r) {
  for (int i = l; i <= r; i++) a[i] = x;
}
inline bool bfs() {
  memcpy(iter, hd, sizeof(hd));
  memset(dis, 0, sizeof(dis));
  int l = 0, r = 0;
  q[++r] = S;
  dis[S] = 1;
  while (l < r) {
    int x = q[++l];
    for (int i = hd[x], y; i; i = e[i].nxt)
      if (e[i].w && !dis[y = e[i].v]) {
        dis[y] = dis[x] + 1;
        q[++r] = y;
      }
  }
  return dis[T];
}
int dfs(int x, int f) {
  if (x == T || !f) return f;
  int sf = 0, y;
  for (int &i = iter[x]; i; i = e[i].nxt)
    if (e[i].w && dis[y = e[i].v] == dis[x] + 1) {
      int w = dfs(y, min(f, e[i].w));
      e[i].w -= w;
      e[i ^ 1].w += w;
      f -= w;
      sf += w;
      if (!f) break;
    }
  if (!sf) dis[x] = 0;
  return sf;
}
int dinic() {
  int ans = 0;
  while (bfs()) ans += dfs(S, inf);
  return ans;
}
int main() {
  scanf("%d%d", &n, &m);
  build(r1, 0, 1, n, 0);
  build(r2, 0, 1, n, 1);
  for (int i = 1, x1, y1, x2, y2; i <= m; i++) {
    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    c[i * 2 - 1] = (st){x1 - 1, y1, y2, 0};
    c[i * 2] = (st){x2, y1, y2, 1};
  }
  sort(c + 1, c + m * 2 + 1, cmp);
  for (int i = 1; i <= m * 2; i++)
    if (!c[i].f)
      ins(c[i].x, c[i].l, c[i].r);
    else
      upd(c[i].x, c[i].l, c[i].r);
  ins(n, 1, n);
  T = ++cnt;
  build2(r1, 1, n, S);
  build2(r2, 1, n, T);
  printf("%d\n", dinic());
  return 0;
}
