#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
const int kMaxN = 4e4 + 5, kMaxM = 8e6 + 5, kInf = 1e9;
int n, q, m, s, t, tot = 1, cnt;
int idx[kMaxN << 2], idd[kMaxN << 2];
int tail[kMaxN * 20], pre[kMaxM], to[kMaxM], val[kMaxM], dep[kMaxN * 20], cur[kMaxN * 20];
bool vis[kMaxN * 20];
std::vector<std::pair<int, int>> vs[kMaxN], vt[kMaxN];
void add(int u, int v, int w) {
to[++tot] = v, pre[tot] = tail[u], val[tot] = w, tail[u] = tot;
}
void adde(int u, int v, int w) {
add(u, v, w), add(v, u, 0);
}
bool bfs() {
std::queue<int> q;
for (int i = 1; i <= cnt; ++i) {
dep[i] = kInf, cur[i] = tail[i], vis[i] = 0;
}
q.emplace(s), dep[s] = 0, vis[s] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = tail[u]; i; i = pre[i]) {
int v = to[i], w = val[i];
if (!w || vis[v]) continue;
vis[v] = 1, dep[v] = dep[u] + 1, q.emplace(v);
}
}
return vis[t];
}
int dfs(int u, int flow) {
if (u == t || !flow) return flow;
int ret = 0;
for (int &i = cur[u]; i && flow; i = pre[i]) {
int v = to[i], w = val[i];
if (dep[v] == dep[u] + 1 && w) {
int tmp = dfs(v, std::min(w, flow));
if (!tmp) dep[v] = 0;
flow -= tmp, ret += tmp;
val[i] -= tmp, val[i ^ 1] += tmp;
}
}
return ret;
}
void build(int x, int l, int r) {
idx[x] = idd[x] = ++cnt;
if (l == r) {
adde(idx[x], t, 1);
return;
}
int mid = (l + r) >> 1;
build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r);
adde(idx[x], idx[x << 1], kInf), adde(idx[x], idx[x << 1 | 1], kInf);
}
void update(int x, int l, int r, int ql, int qr, int v) {
if (l >= ql && r <= qr) {
if (!~v) idd[x] = idx[x];
else idd[x] = -1;
return;
}
int mid = (l + r) >> 1;
idd[x] = ++cnt;
if (ql <= mid) update(x << 1, l, mid, ql, qr, v);
if (mid < qr) update(x << 1 | 1, mid + 1, r, ql, qr, v);
if (~idd[x << 1]) adde(idd[x], idd[x << 1], kInf);
if (~idd[x << 1 | 1]) adde(idd[x], idd[x << 1 | 1], kInf);
}
void dickdreamer() {
std::cin >> n >> q;
for (int i = 1; i <= q; ++i) {
int x1, y1, x2, y2;
std::cin >> x1 >> y1 >> x2 >> y2;
vs[x1].emplace_back(y1, y2), vt[x2 + 1].emplace_back(y1, y2);
}
s = 1, t = cnt = 2;
build(1, 1, n);
for (int i = 1; i <= n; ++i) {
for (auto [l, r] : vt[i])
update(1, 1, n, l, r, -1);
for (auto [l, r] : vs[i])
update(1, 1, n, l, r, 1);
if (~idd[1]) adde(s, idd[1], 1);
}
int ans = 0;
for (; bfs(); ans += dfs(s, kInf)) {}
std::cout << ans << '\n';
}
int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
while (T--) dickdreamer();
return 0;
}