#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5, M = N * 30, inf = 1e9;
int n, m, stok, istok, sz, d[M], ptr[M];
bool used[N][N];
struct edge {
  int a, b, cap, flow;
};
vector<edge> e;
vector<int> g[M], down, up, tdown, tup;
inline void add_edge(int a, int b, int cap) {
  edge e1 = {a, b, cap, 0}, e2 = {b, a, 0, 0};
  g[a].push_back((int)e.size());
  e.push_back(e1);
  g[b].push_back((int)e.size());
  e.push_back(e2);
}
inline bool bfs() {
  for (int i = 1; i <= sz; i++) {
    d[i] = -1;
  }
  d[istok] = 0;
  queue<int> q;
  q.push(istok);
  while (!q.empty() && d[stok] == -1) {
    int v = q.front();
    q.pop();
    for (int x : g[v]) {
      int to = e[x].b;
      if (d[to] == -1 && e[x].flow < e[x].cap) {
        d[to] = d[v] + 1;
        q.push(to);
      }
    }
  }
  return d[stok] != -1;
}
int dfs(int v, int flow) {
  if (!flow) {
    return 0;
  }
  if (v == stok) {
    return flow;
  }
  for (; ptr[v] < g[v].size(); ptr[v]++) {
    int id = g[v][ptr[v]], to = e[id].b;
    if (d[to] != d[v] + 1) {
      continue;
    }
    int x = dfs(to, min(flow, e[id].cap - e[id].flow));
    if (x) {
      e[id].flow += x;
      e[id ^ 1].flow -= x;
      return x;
    }
  }
  return 0;
}
void build(int v, int l, int r, bool down, vector<int> &a, vector<int> &t) {
  t[v] = ++sz;
  if (l == r) {
    a[l] = t[v];
    return;
  }
  int mid = (r + l) >> 1;
  build(v + v, l, mid, down, a, t);
  build(v + v + 1, mid + 1, r, down, a, t);
  if (down) {
    add_edge(t[v], t[v + v], inf);
    add_edge(t[v], t[v + v + 1], inf);
  } else {
    add_edge(t[v + v], t[v], inf);
    add_edge(t[v + v + 1], t[v], inf);
  }
}
void upd(int v, int l, int r, int tl, int tr, bool down, int vv,
         vector<int> &t) {
  if (l > r || l > tr || tl > r) {
    return;
  }
  if (tl <= l && r <= tr) {
    if (down) {
      add_edge(vv, t[v], inf);
    } else {
      add_edge(t[v], vv, inf);
    }
    return;
  }
  int mid = (r + l) >> 1;
  upd(v + v, l, mid, tl, tr, down, vv, t);
  upd(v + v + 1, mid + 1, r, tl, tr, down, vv, t);
}
inline void add(int x1, int y1, int x2, int y2) {
  int nxt = ++sz;
  upd(1, 1, n, x1, x2, true, nxt, tdown);
  upd(1, 1, n, y1, y2, false, nxt, tup);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    for (int j = y1; j <= y2; j++) {
      for (int jj = x1; jj <= x2; jj++) {
        used[j][jj] = true;
      }
    }
  }
  down.resize(n + 1);
  up.resize(n + 1);
  tdown.resize(4 * n);
  tup.resize(4 * n);
  istok = ++sz;
  stok = ++sz;
  build(1, 1, n, true, down, tdown);
  build(1, 1, n, false, up, tup);
  for (int i = 1; i <= n; i++) {
    used[i][n + 1] = used[n + 1][i] = true;
  }
  for (int i = 1; i <= n; i++) {
    add_edge(down[i], stok, 1);
    add_edge(istok, up[i], 1);
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (!used[i][j]) {
        int k = j;
        while (!used[i][k]) {
          k++;
        }
        k--;
        int last = i;
        for (int ii = i; ii <= n; ii++) {
          bool p = true;
          for (int jj = j; jj <= k; jj++) {
            if (used[ii][jj]) {
              p = false;
              break;
            }
          }
          if (!p) {
            break;
          }
          last = ii;
        }
        for (int ii = i; ii <= last; ii++) {
          for (int jj = j; jj <= k; jj++) {
            used[ii][jj] = true;
          }
        }
        add(i, j, last, k);
      }
    }
  }
  int ans = 0;
  while (true) {
    if (!bfs()) {
      break;
    }
    memset(ptr, 0, sizeof(ptr));
    while (int x = dfs(istok, inf)) {
      ans += x;
    }
  }
  cout << ans;
}
