#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x) {
  x = 0;
  char c = getchar();
  bool flag = false;
  while (!isdigit(c)) {
    if (c == '-') flag = true;
    c = getchar();
  }
  while (isdigit(c)) {
    x = (x << 1) + (x << 3) + (c ^ 48);
    c = getchar();
  }
  if (flag) x = -x;
}
int n, m, s, t, tot, root = 1;
int id[50010], tag[50010], cur[10000010], d[10000010];
struct node {
  int l, r, v;
  node(int a = 0, int b = 0, int c = 0) { l = a, r = b, v = c; }
};
vector<node> ve[50010];
struct edge {
  int to, nxt, v;
  edge(int a = 0, int b = 0, int c = 0) { to = a, nxt = b, v = c; }
} e[10000010];
int head[10000010], edge_cnt = 1;
void add(int from, int to, int val) {
  e[++edge_cnt] = edge(to, head[from], val), head[from] = edge_cnt;
  e[++edge_cnt] = edge(from, head[to], 0), head[to] = edge_cnt;
}
bool bfs() {
  for (int i = 1; i <= tot; ++i) d[i] = 0, cur[i] = head[i];
  queue<int> q;
  q.push(s), d[s] = 1;
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = head[x]; i; i = e[i].nxt) {
      int y = e[i].to;
      if (d[y] || !e[i].v) continue;
      d[y] = d[x] + 1, q.push(y);
    }
  }
  return d[t];
}
int dfs(int x, int lim) {
  if (x == t) return lim;
  int res = lim, flow;
  for (int &i = cur[x]; i; i = e[i].nxt) {
    int y = e[i].to, v = e[i].v;
    if (d[y] != d[x] + 1 || !v) continue;
    if (flow = dfs(y, min(res, v))) {
      res -= flow, e[i].v -= flow, e[i ^ 1].v += flow;
      if (!res) break;
    }
  }
  return lim - res;
}
int dinic() {
  int v = 0, flow;
  while (bfs())
    while (flow = dfs(s, 1000000000)) v += flow;
  return v;
}
void pushup(int cur) {
  id[cur] = ++tot;
  if (!tag[(cur << 1)]) add(id[cur], id[(cur << 1)], 1000000000);
  if (!tag[(cur << 1 | 1)]) add(id[cur], id[(cur << 1 | 1)], 1000000000);
}
void build(int l, int r, int cur) {
  if (l == r) {
    add(id[cur] = ++tot, t, 1);
    return;
  }
  build(l, ((l + r) >> 1), (cur << 1)),
      build(((l + r) >> 1) + 1, r, (cur << 1 | 1)), pushup(cur);
}
void modify(int L, int R, int l, int r, int v, int cur) {
  if (L <= l && R >= r) {
    tag[cur] += v;
    return;
  }
  if (L <= ((l + r) >> 1)) modify(L, R, l, ((l + r) >> 1), v, (cur << 1));
  if (R > ((l + r) >> 1))
    modify(L, R, ((l + r) >> 1) + 1, r, v, (cur << 1 | 1));
  pushup(cur);
}
int main() {
  read(n), read(m), s = ++tot, t = ++tot;
  for (int i = 1; i <= m; ++i) {
    int u, d, l, r;
    read(u), read(l), read(d), read(r);
    ve[u].push_back(node(l, r, 1)), ve[d + 1].push_back(node(l, r, -1));
  }
  build(1, n, root);
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j < ve[i].size(); ++j)
      modify(ve[i][j].l, ve[i][j].r, 1, n, ve[i][j].v, root);
    add(s, ++tot, 1);
    if (!tag[root]) add(tot, id[root], 1000000000);
  }
  printf("%d", dinic());
  return 0;
}
