#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int MAXN = 10000;
const int MAXBLOCKS = 10000;
const int MAXRECT = 4 * MAXBLOCKS;
const int MAXGN = 2 + 4 * MAXN + MAXRECT;
const int MAXGM = 6 * MAXN + 2 * 2 * 14 * MAXRECT;
typedef struct R {
  int lx, ly, hx, hy;
} R;
int n, h, w;
R b[MAXBLOCKS];
int nb;
bool blocked[MAXN][MAXN];
R r[MAXRECT];
int nr;
typedef struct MF {
  int n, m;
  int ghead[MAXGN], gnxt[2 * MAXGM], gto[2 * MAXGM], gcap[2 * MAXGM];
  void init(int _n) {
    n = _n, m = 0;
    for (int i = (0); i < (n); ++i) ghead[i] = -1;
  }
  void addedge(int a, int b, int c) {
    gnxt[2 * m + 0] = ghead[a], ghead[a] = 2 * m + 0, gto[2 * m + 0] = b,
                 gcap[2 * m + 0] = c;
    gnxt[2 * m + 1] = ghead[b], ghead[b] = 2 * m + 1, gto[2 * m + 1] = a,
                 gcap[2 * m + 1] = 0;
    ++m;
  }
  int d[MAXGN];
  int q[MAXGN], qhead, qtail;
  int cur[MAXGN];
  int dinic(int s, int t) {
    int ret = 0;
    int niter = 0;
    while (true) {
      for (int i = (0); i < (n); ++i) d[i] = INT_MAX;
      qhead = qtail = 0;
      d[s] = 0, q[qhead++] = s;
      while (qtail < qhead && d[t] == INT_MAX) {
        int at = q[qtail++];
        for (int x = ghead[at]; x != -1; x = gnxt[x]) {
          int to = gto[x];
          if (gcap[x] == 0 || d[to] != INT_MAX) continue;
          d[to] = d[at] + 1;
          q[qhead++] = to;
        }
      }
      if (d[t] == INT_MAX) {
        return ret;
      }
      for (int i = (0); i < (n); ++i) cur[i] = ghead[i];
      ret += dfs(s, t, INT_MAX);
      ++niter;
    }
  }
  int dfs(int at, int t, int rem) {
    int ret = 0;
    if (at == t) return rem;
    if (d[at] >= d[t]) return 0;
    for (; cur[at] != -1; cur[at] = gnxt[cur[at]]) {
      int to = gto[cur[at]], cap = gcap[cur[at]];
      if (d[to] != d[at] + 1 || cap == 0) continue;
      int now = dfs(to, t, min(cap, rem));
      rem -= now;
      ret += now;
      gcap[cur[at]] -= now;
      gcap[cur[at] ^ 1] += now;
      if (rem == 0) return ret;
    }
    return ret;
  }
  void print() {
    for (int i = (0); i < (m); ++i)
      if (gcap[2 * i + 0] == 0)
        printf("used %d->%d\n", gto[2 * i + 1], gto[2 * i + 0]);
  }
} MF;
MF g;
int solve() {
  memset(blocked, false, sizeof(blocked));
  h = w = n;
  for (int i = (0); i < (nb); ++i)
    for (int x = (b[i].lx); x <= (b[i].hx); ++x)
      for (int y = (b[i].ly); y <= (b[i].hy); ++y) blocked[x][y] = true;
  nr = 0;
  for (int lx = (0); lx < (h); ++lx)
    for (int ly = (0); ly < (w); ++ly)
      if (!blocked[lx][ly]) {
        int hy = ly;
        while (hy + 1 < w && !blocked[lx][hy + 1]) ++hy;
        int hx = lx;
        while (hx + 1 < h) {
          bool ok = true;
          for (int y = (ly); y <= (hy); ++y)
            if (blocked[hx + 1][y]) {
              ok = false;
              break;
            }
          if (!ok)
            break;
          else
            ++hx;
        }
        r[nr].lx = lx, r[nr].ly = ly, r[nr].hx = hx, r[nr].hy = hy, ++nr;
        for (int x = (lx); x <= (hx); ++x)
          for (int y = (ly); y <= (hy); ++y) blocked[x][y] = true;
      }
  g.init(2 + 4 * n + nr);
  for (int i = (0); i < (n); ++i) g.addedge(0, 2 + n + i, 1);
  for (int i = (1); i < (n); ++i)
    g.addedge(2 + 2 * i, 2 + i, n), g.addedge(2 + 2 * i + 1, 2 + i, n);
  for (int i = (0); i < (n); ++i) g.addedge(2 + 3 * n + i, 1, 1);
  for (int i = (1); i < (n); ++i)
    g.addedge(2 + 2 * n + i, 2 + 2 * n + 2 * i, n),
        g.addedge(2 + 2 * n + i, 2 + 2 * n + 2 * i + 1, n);
  for (int i = (0); i < (nr); ++i) {
    {
      int lidx = n + r[i].lx, ridx = n + r[i].hx + 1;
      for (; lidx < ridx; lidx >>= 1, ridx >>= 1) {
        if (lidx & 1) g.addedge(2 + lidx, 2 + 4 * n + i, n), ++lidx;
        if (ridx & 1) --ridx, g.addedge(2 + ridx, 2 + 4 * n + i, n);
      }
    }
    {
      int lidx = n + r[i].ly, ridx = n + r[i].hy + 1;
      for (; lidx < ridx; lidx >>= 1, ridx >>= 1) {
        if (lidx & 1) g.addedge(2 + 4 * n + i, 2 + 2 * n + lidx, n), ++lidx;
        if (ridx & 1) --ridx, g.addedge(2 + 4 * n + i, 2 + 2 * n + ridx, n);
      }
    }
  }
  int ret = g.dinic(0, 1);
  return ret;
}
void run() {
  scanf("%d", &n);
  scanf("%d", &nb);
  for (int i = (0); i < (nb); ++i) {
    int lx, ly, hx, hy;
    scanf("%d%d%d%d", &b[i].lx, &b[i].ly, &b[i].hx, &b[i].hy);
    --b[i].lx, --b[i].ly, --b[i].hx, --b[i].hy;
  }
  printf("%d\n", solve());
}
void stress() {
  n = MAXN;
  nb = MAXBLOCKS - 1;
  for (int i = (0); i < (nb); ++i) {
    b[i].lx = i, b[i].hx = i, b[i].ly = (rand() * 1000 + rand()) % n,
    b[i].hy = n - 1;
  }
  clock_t begin = clock();
  printf("%d\n", solve());
  clock_t end = clock();
  printf("%.9lf\n", (double)(end - begin) / CLOCKS_PER_SEC);
}
int main() {
  run();
  return 0;
}
