#include <bits/stdc++.h>
using namespace std;
const long long INF = 1LL * 1001 * 1001 * 1001 * 1001 * 1001 * 1001;
const int N = 10000;
struct edge {
  long long a, b, cap, flow;
  edge(long long a, long long b, long long cap)
      : a(a), b(b), cap(cap), flow(0) {}
  long long cap_to(long long u) { return u == b ? cap - flow : flow; }
  long long another(long long u) { return u == b ? a : b; }
  void add_flow(long long u, long long first) {
    flow += (u == b ? first : -first);
  }
};
struct dinic_graph {
  vector<edge> e;
  vector<long long> g[N];
  long long pos[N], d[N], p[N];
  void add_edge(long long a, long long b, long long c) {
    g[a].push_back((int)e.size());
    g[b].push_back((int)e.size());
    e.push_back(edge(a, b, c));
  }
  bool bfs(long long S, long long T) {
    d[S] = 1;
    queue<long long> q;
    q.push(S);
    while (q.size()) {
      long long u = q.front();
      q.pop();
      if (u == T) return 1;
      for (int i = 0; i < g[u].size(); i++) {
        long long to = e[g[u][i]].another(u);
        if (!d[to] && e[g[u][i]].cap_to(to)) {
          d[to] = d[u] + 1;
          q.push(to);
        }
      }
    }
    return 0;
  }
  bool dfs(long long u, long long t) {
    if (u == t) return 1;
    for (; pos[u] < g[u].size(); pos[u]++) {
      long long to = e[g[u][pos[u]]].another(u);
      if (d[to] == d[u] + 1 && e[g[u][pos[u]]].cap_to(to)) {
        p[to] = g[u][pos[u]];
        if (dfs(to, t)) return 1;
      }
    }
    return 0;
  }
  long long dinic(long long S, long long T) {
    long long max_flow = 0;
    while (1) {
      memset(d, 0, sizeof(d));
      if (!bfs(S, T)) return max_flow;
      memset(pos, 0, sizeof(pos));
      while (dfs(S, T)) {
        long long cur_f = INF;
        for (long long u = T; u != S; u = e[p[u]].another(u))
          cur_f = min(cur_f, e[p[u]].cap_to(u));
        for (long long u = T; u != S; u = e[p[u]].another(u))
          e[p[u]].add_flow(u, cur_f);
        max_flow += cur_f;
      }
    }
  }
};
int n, m;
int x1[55], mezhdy[55], x2[55], nami[55];
vector<int> x, y;
dinic_graph g;
bool in(double x, double y, int pos) {
  return x >= min(x1[pos], x2[pos]) && x <= max(x1[pos], x2[pos]) &&
         y >= min(mezhdy[pos], nami[pos]) && y <= max(mezhdy[pos], nami[pos]);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    cin >> x1[i] >> mezhdy[i] >> x2[i] >> nami[i];
    x2[i]++;
    nami[i]++;
    x.push_back(x1[i]);
    x.push_back(x2[i]);
    y.push_back(mezhdy[i]);
    y.push_back(nami[i]);
  }
  sort(x.begin(), x.end());
  sort(y.begin(), y.end());
  x.erase(unique(x.begin(), x.end()), x.end());
  y.erase(unique(y.begin(), y.end()), y.end());
  int S = 0;
  int T = (int)x.size() + (int)y.size() + 1;
  for (int i = 1; i < x.size(); i++) g.add_edge(S, i, x[i] - x[i - 1]);
  for (int i = 1; i < y.size(); i++)
    g.add_edge(i + x.size(), T, y[i] - y[i - 1]);
  for (int i = 1; i < x.size(); i++)
    for (int j = 1; j < y.size(); j++) {
      double xx = 1.0 * (x[i] + x[i - 1]) / 2;
      double yy = 1.0 * (y[j] + y[j - 1]) / 2;
      bool ok = 0;
      for (int p = 0; p < m; p++)
        if (in(xx, yy, p)) ok = 1;
      if (ok) g.add_edge(i, j + x.size(), INF);
    }
  cout << g.dinic(S, T);
}
