#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
inline long long getint() {
  long long _x = 0, _tmp = 1;
  char _tc = getchar();
  while ((_tc < '0' || _tc > '9') && _tc != '-') _tc = getchar();
  if (_tc == '-') _tc = getchar(), _tmp = -1;
  while (_tc >= '0' && _tc <= '9') _x *= 10, _x += (_tc - '0'), _tc = getchar();
  return _x * _tmp;
}
inline long long add(long long _x, long long _y,
                     long long _mod = 1000000007LL) {
  _x += _y;
  return _x >= _mod ? _x - _mod : _x;
}
inline long long sub(long long _x, long long _y,
                     long long _mod = 1000000007LL) {
  _x -= _y;
  return _x < 0 ? _x + _mod : _x;
}
inline long long mul(long long _x, long long _y,
                     long long _mod = 1000000007LL) {
  _x *= _y;
  return _x >= _mod ? _x % _mod : _x;
}
long long mypow(long long _a, long long _x, long long _mod) {
  if (_x == 0) return 1LL;
  long long _ret = mypow(mul(_a, _a, _mod), _x >> 1, _mod);
  if (_x & 1) _ret = mul(_ret, _a, _mod);
  return _ret;
}
long long mymul(long long _a, long long _x, long long _mod) {
  if (_x == 0) return 0LL;
  long long _ret = mymul(add(_a, _a, _mod), _x >> 1, _mod);
  if (_x & 1) _ret = add(_ret, _a, _mod);
  return _ret;
}
inline bool equal(double _x, double _y) {
  return _x > _y - 1e-9 && _x < _y + 1e-9;
}
int __ = 1, _cs;
struct Maxflow {
  static const int MAXV = 100010;
  static const int INF = 1000000;
  struct Edge {
    int v, c, r;
    Edge(int _v, int _c, int _r) : v(_v), c(_c), r(_r) {}
  };
  int s, t;
  vector<Edge> G[MAXV * 2];
  int iter[MAXV * 2], d[MAXV * 2], gap[MAXV * 2], tot;
  void init(int x) {
    tot = x + 2;
    s = x + 1, t = x + 2;
    for (int i = 0; i <= tot; i++) {
      G[i].clear();
      iter[i] = d[i] = gap[i] = 0;
    }
  }
  void addEdge(int u, int v, int c) {
    G[u].push_back(Edge(v, c, (int)(G[v]).size()));
    G[v].push_back(Edge(u, 0, (int)(G[u]).size() - 1));
  }
  int dfs(int p, int flow) {
    if (p == t) return flow;
    int ret = 0;
    for (int &i = iter[p]; i < (int)(G[p]).size(); i++) {
      Edge &e = G[p][i];
      if (e.c > 0 && d[p] == d[e.v] + 1) {
        int f = dfs(e.v, min(flow, e.c));
        ret += f;
        flow -= f;
        e.c -= f;
        G[e.v][e.r].c += f;
        if (flow == 0) {
          break;
        }
      }
    }
    if (ret > 0) {
      return ret;
    }
    if ((--gap[d[p]]) == 0)
      d[s] = tot;
    else {
      d[p]++;
      iter[p] = 0;
      ++gap[d[p]];
    }
    return 0;
  }
  int solve() {
    int res = 0;
    gap[0] = tot;
    for (res = 0; d[s] < tot; res += dfs(s, INF))
      ;
    return res;
  }
} flow;
int tg[10101 << 2];
int mn[10101 << 2], mx[10101 << 2];
void push(int no, int l, int r) {
  if (!tg[no]) return;
  tg[(no << 1)] += tg[no];
  mn[(no << 1)] += tg[no];
  mx[(no << 1)] += tg[no];
  tg[(1 + (no << 1))] += tg[no];
  mn[(1 + (no << 1))] += tg[no];
  mx[(1 + (no << 1))] += tg[no];
  tg[no] = 0;
}
void modify(int no, int l, int r, int ql, int qr, int qd) {
  if (r < ql or l > qr) return;
  if (ql <= l and r <= qr) {
    tg[no] += qd;
    mn[no] += qd;
    mx[no] += qd;
    return;
  }
  push(no, l, r);
  modify((no << 1), l, ((l + r) >> 1), ql, qr, qd);
  modify((1 + (no << 1)), ((l + r) >> 1) + 1, r, ql, qr, qd);
  mn[no] = min(mn[(no << 1)], mn[(1 + (no << 1))]);
  mx[no] = max(mx[(no << 1)], mx[(1 + (no << 1))]);
}
int id[10101 << 2], stmp;
void mark(int no, int l, int r) {
  id[no] = ++stmp;
  if (l == r) return;
  mark((no << 1), l, ((l + r) >> 1));
  mark((1 + (no << 1)), ((l + r) >> 1) + 1, r);
}
void build_edge(int no, int l, int r) {
  if (l == r) {
    flow.addEdge(flow.s, id[no], 1);
    flow.addEdge(id[no] + stmp, flow.t, 1);
    return;
  }
  flow.addEdge(id[(no << 1)], id[no], 10101);
  flow.addEdge(id[(1 + (no << 1))], id[no], 10101);
  flow.addEdge(id[no] + stmp, id[(no << 1)] + stmp, 10101);
  flow.addEdge(id[no] + stmp, id[(1 + (no << 1))] + stmp, 10101);
  build_edge((no << 1), l, ((l + r) >> 1));
  build_edge((1 + (no << 1)), ((l + r) >> 1) + 1, r);
}
void build() {}
int n, m;
vector<pair<pair<int, int>, int> > dlt[10101];
vector<int> candx;
void init() {
  n = getint();
  mark(1, 1, n);
  flow.init(stmp + stmp);
  build_edge(1, 1, n);
  m = getint();
  while (m--) {
    int sdfjklsj = getint();
    int sdfjklsl = getint();
    int sdfjklsk = getint();
    int sdfjklsm = getint();
    dlt[sdfjklsj].push_back({{sdfjklsl, sdfjklsm}, +1});
    dlt[sdfjklsk + 1].push_back({{sdfjklsl, sdfjklsm}, -1});
    candx.push_back(sdfjklsj);
    candx.push_back(sdfjklsk + 1);
  }
}
vector<int> lid;
void find_id(int no, int l, int r, int ql, int qr) {
  if (r < ql or l > qr) return;
  if (ql <= l and r <= qr) {
    lid.push_back(id[no]);
    return;
  }
  find_id((no << 1), l, ((l + r) >> 1), ql, qr);
  find_id((1 + (no << 1)), ((l + r) >> 1) + 1, r, ql, qr);
}
void gogo(int no, int l, int r) {
  if (mn[no] > 0) return;
  if (mx[no] == 0) {
    for (auto ii : lid) flow.addEdge(ii, id[no] + stmp, 10101);
    return;
  }
  if (l == r) return;
  push(no, l, r);
  gogo((no << 1), l, ((l + r) >> 1));
  gogo((1 + (no << 1)), ((l + r) >> 1) + 1, r);
}
void solve() {
  if (candx.empty()) {
    printf("%d\n", n);
    exit(0);
  }
  sort(candx.begin(), candx.end());
  candx.resize(unique(candx.begin(), candx.end()) - candx.begin());
  if (candx[0] > 1) {
    lid.clear();
    find_id(1, 1, n, 1, candx[0] - 1);
    gogo(1, 1, n);
  }
  for (size_t _ = 0; _ < candx.size(); _++) {
    int x = candx[_];
    int til = _ + 1 < candx.size() ? candx[_ + 1] - 1 : n;
    for (auto i : dlt[x])
      modify(1, 1, n, i.first.first, i.first.second, i.second);
    lid.clear();
    find_id(1, 1, n, x, til);
    gogo(1, 1, n);
  }
  printf("%d\n", flow.solve());
}
int main() {
  build();
  while (__--) {
    init();
    solve();
  }
}
