#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int ldx[55], cxy[55], yk[55], yyf[55], lsx[110], lsy[110];
bool flag[110][110];
class edge {
 public:
  int e, nxt, cap;
  edge(int e1 = -1, int nxt1 = -1, int cap1 = 0) {
    e = e1, nxt = nxt1, cap = cap1;
  }
};
int S, T, n, m, sum;
int dep[210];
bool vis[210];
class graph {
 public:
  edge g[3000000];
  int head[210], tmpcnt;
  int cur[210];
  void init() {
    memset(head, 255, sizeof(head));
    tmpcnt = 0;
  }
  void addedge(int s, int e, int cap) {
    if (cap == 0) return;
    g[tmpcnt] = edge(e, head[s], cap), head[s] = tmpcnt++;
    g[tmpcnt] = edge(s, head[e], 0), head[e] = tmpcnt++;
  }
  bool bfs() {
    memset(vis, 0, sizeof(vis));
    memset(dep, 0, sizeof(dep));
    queue<int> q;
    q.push(S);
    vis[S] = 1;
    while (!q.empty()) {
      int fr = q.front();
      q.pop();
      for (int i = head[fr]; i != -1; i = g[i].nxt) {
        if (g[i].cap > 0 && !vis[g[i].e]) {
          dep[g[i].e] = dep[fr] + 1;
          vis[g[i].e] = 1;
          q.push(g[i].e);
        }
      }
    }
    return vis[T];
  }
  int dfs(int np, int maxflow) {
    int f;
    int flow = 0;
    if (np == T || !maxflow) return maxflow;
    for (int i = cur[np]; i != -1; i = g[i].nxt) {
      cur[np] = i;
      if (g[i].cap > 0 && dep[g[i].e] == dep[np] + 1 &&
          (f = dfs(g[i].e, min(g[i].cap, maxflow))) > 0) {
        g[i].cap -= f;
        g[i ^ 1].cap += f;
        flow += f;
        maxflow -= f;
        if (!maxflow) break;
      }
    }
    return flow;
  }
  int dinic() {
    int out = 0;
    while (bfs()) memcpy(cur, head, sizeof(cur)), out += dfs(S, INF);
    return out;
  }
} G;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d%d", &ldx[i], &yk[i], &cxy[i], &yyf[i]);
    cxy[i]++;
    yyf[i]++;
    lsx[i * 2 - 1] = ldx[i];
    lsx[i * 2] = cxy[i];
    lsy[i * 2 - 1] = yk[i];
    lsy[i * 2] = yyf[i];
  }
  sort(lsx + 1, lsx + m * 2 + 1);
  sort(lsy + 1, lsy + m * 2 + 1);
  int endx = unique(lsx + 1, lsx + m * 2 + 1) - lsx - 1,
      endy = unique(lsy + 1, lsy + m * 2 + 1) - lsy - 1;
  G.init();
  S = endx + endy + 1;
  T = endx + endy + 2;
  for (int i = 1; i < endx; i++) G.addedge(S, i, lsx[i + 1] - lsx[i]);
  for (int i = 1; i < endy; i++) G.addedge(endx + i, T, lsy[i + 1] - lsy[i]);
  for (int i = 1; i <= m; i++) {
    ldx[i] = lower_bound(lsx + 1, lsx + endx + 1, ldx[i]) - lsx;
    cxy[i] = lower_bound(lsx + 1, lsx + endx + 1, cxy[i]) - lsx;
    yk[i] = lower_bound(lsy + 1, lsy + endy + 1, yk[i]) - lsy;
    yyf[i] = lower_bound(lsy + 1, lsy + endy + 1, yyf[i]) - lsy;
    for (int j = ldx[i]; j < cxy[i]; j++) {
      for (int k = yk[i]; k < yyf[i]; k++) flag[j][k] = 1;
    }
  }
  for (int i = 1; i < endx; i++) {
    for (int j = 1; j < endy; j++) {
      if (flag[i][j]) G.addedge(i, j + endx, 0x3f3f3f3f);
    }
  }
  printf("%d\n", G.dinic());
  return 0;
}
