#include <bits/stdc++.h>
using namespace std;
const int N = 10010, inf = 1061109567;
struct Tree {
  int l, r;
} t[N << 2];
struct node {
  int to, flow, nxt;
} h[5000100];
int n, m, S, T, cnt, D, tot, head[500100], he[N], dep[500100];
bool mp[N][N];
vector<pair<int, int> > ve;
int read() {
  int aa = 0, bb = 1;
  char cc = getchar();
  while (cc > '9' || cc < '0') {
    if (cc == '-') bb = -1;
    cc = getchar();
  }
  while (cc >= '0' && cc <= '9') {
    aa = (aa << 3) + (aa << 1) + (cc ^ '0');
    cc = getchar();
  }
  return aa * bb;
}
void add(int x, int y, int flow) {
  h[++tot].to = y;
  h[tot].flow = flow;
  h[tot].nxt = head[x];
  head[x] = tot;
}
void link(int x, int y, int flow) {
  add(x, y, flow);
  add(y, x, 0);
}
void build(int x, int l, int r) {
  t[x].l = l;
  t[x].r = r;
  if (l == r) return cnt = max(cnt, x), void();
  int mid = l + r >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
}
void query(int x, int l, int r, int id, int opt) {
  if (l <= t[x].l && t[x].r <= r) {
    if (opt)
      link(id, x + D, t[x].r - t[x].l + 1);
    else
      link(x, id, t[x].r - t[x].l + 1);
    return;
  }
  int mid = t[x].l + t[x].r >> 1;
  if (l <= mid) query(x << 1, l, r, id, opt);
  if (r > mid) query(x << 1 | 1, l, r, id, opt);
}
void Link(int x, int opt) {
  if (t[x].l == t[x].r) {
    if (opt) link(x + D, T, 1);
    return;
  }
  Link(x << 1, opt);
  Link(x << 1 | 1, opt);
  int mid = t[x].l + t[x].r >> 1;
  if (opt)
    link(x + D, (x << 1) + D, mid - t[x].l + 1),
        link(x + D, (x << 1 | 1) + D, t[x].r - mid);
  else
    link(x, x << 1, mid - t[x].l + 1), link(x, x << 1 | 1, t[x].r - mid);
}
bool bfs() {
  queue<int> q;
  memset(dep, 0, sizeof(dep));
  dep[S] = 1;
  q.push(S);
  while (q.size()) {
    int x = q.front();
    q.pop();
    for (int i = head[x]; i; i = h[i].nxt) {
      int y = h[i].to;
      if (h[i].flow > 0 && !dep[y]) dep[y] = dep[x] + 1, q.push(y);
    }
  }
  return dep[T];
}
int dfs(int x, int flow) {
  if (x == T || flow <= 0) return flow;
  int res = flow;
  for (int i = head[x]; i; i = h[i].nxt) {
    int y = h[i].to;
    if (h[i].flow <= 0 || dep[y] != dep[x] + 1) continue;
    int tmp = dfs(y, min(res, h[i].flow));
    if (!tmp) dep[y] = 0;
    h[i].flow -= tmp;
    h[i ^ 1].flow += tmp;
    res -= tmp;
    if (!res) break;
  }
  return flow - res;
}
int dinic() {
  int ans = 0;
  while (bfs()) ans += dfs(S, inf);
  return ans;
}
int main() {
  n = read();
  m = read();
  tot = 1;
  int x, y, xx, yy;
  for (int i = 1; i <= m; i++) {
    x = read();
    y = read();
    xx = read();
    yy = read();
    for (int j = x; j <= xx; j++)
      for (int k = y; k <= yy; k++) mp[j][k] = 1;
  }
  for (int i = 1; i <= n; i++) mp[n + 1][i] = 1;
  build(1, 1, n);
  D = cnt;
  cnt += cnt;
  S = ++cnt;
  T = ++cnt;
  Link(1, 0);
  Link(1, 1);
  link(S, 1, n);
  for (int i = 1; i <= n + 1; i++) {
    ve.clear();
    for (int j = 1; j <= n; j++) {
      if (!mp[i][j])
        he[j]++;
      else if (he[j])
        ve.push_back(make_pair(j, he[j])), he[j] = 0;
    }
    int p = 0;
    for (int j = 0; j < ve.size(); j++) {
      p = j;
      while (p + 1 < ve.size() && ve[p].first + 1 == ve[p + 1].first &&
             ve[p].second == ve[p + 1].second)
        p++;
      cnt++;
      query(1, ve[j].first, ve[p].first, cnt, 0);
      query(1, i - ve[j].second, i - 1, cnt, 1);
      j = p;
    }
  }
  printf("%d\n", dinic());
  return 0;
}
