#include <bits/stdc++.h>
using namespace std;
template <class T>
class is_zero {
 public:
  bool operator()(const T& x) const;
};
template <>
class is_zero<int> {
 public:
  bool operator()(const int& x) const { return x == 0; }
};
template <class WeightT = int, class ZeroPredicator = is_zero<WeightT> >
class flow_graph {
 public:
  typedef const WeightT& const_weight_reference;
  typedef WeightT* weight_array_type;

 private:
  struct edge {
    int v;
    WeightT w;
    edge *next, *rev;
  };
  int v, e;
  edge *pool, *used;
  edge** adj;
  ZeroPredicator zero_predicator;
  edge* add_edge(int u, int v, const_weight_reference w) {
    edge* p = used;
    ++used;
    p->v = v;
    p->w = w;
    p->next = adj[u];
    adj[u] = p;
    return p;
  }
  bool bfs(int s, int t, int* level) {
    memset(level, -1, sizeof(int) * v);
    std::queue<int> q;
    q.push(s);
    level[s] = 0;
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (edge* p = adj[u]; p; p = p->next)
        if (!zero_predicator(p->w) && level[p->v] == -1) {
          level[p->v] = level[u] + 1;
          if (p->v == t) return true;
          q.push(p->v);
        }
    }
    return false;
  }
  WeightT dfs(int u, int t, WeightT lim, edge** cadj, int* level) {
    if (u == t) return lim;
    WeightT flow = 0;
    for (edge*& p = cadj[u]; p; p = p->next)
      if (!zero_predicator(p->w) && level[u] < level[p->v]) {
        WeightT f = dfs(p->v, t, std::min(p->w, lim), cadj, level);
        flow += f;
        lim -= f;
        p->w -= f;
        p->rev->w += f;
        if (zero_predicator(lim)) return flow;
      }
    return flow;
  }
  WeightT dfs(int u, int t, edge** cadj, int* level) {
    WeightT flow = 0;
    for (edge*& p = cadj[u]; p; p = p->next)
      if (!zero_predicator(p->w) && level[u] < level[p->v]) {
        WeightT f = dfs(p->v, t, p->w, cadj, level);
        flow += f;
        p->w -= f;
        p->rev->w += f;
      }
    return flow;
  }

 public:
  flow_graph() {}
  flow_graph(int v, int e, ZeroPredicator zero_predicator = is_zero<WeightT>())
      : v(v), e(e), zero_predicator(zero_predicator) {
    pool = new edge[e * 2];
    adj = new edge*[v];
    memset(pool, 0, sizeof(edge) * e * 2);
    memset(adj, 0, sizeof(edge*) * v);
    used = pool;
  }
  ~flow_graph() {
    delete[] pool;
    delete[] adj;
  }
  void link(int u, int v, const_weight_reference w) {
    edge *p = add_edge(u, v, w), *q = add_edge(v, u, 0);
    p->rev = q;
    q->rev = p;
  }
  WeightT max_flow(int s, int t) {
    int* level = new int[v];
    edge** cadj = new edge*[v];
    WeightT flow = 0;
    while (bfs(s, t, level)) {
      memcpy(cadj, adj, sizeof(edge*) * v);
      flow += dfs(s, t, cadj, level);
    }
    delete[] level;
    delete[] cadj;
    return flow;
  }
};
const int N = 55;
int n, xc, yc;
int xd[N * 2], yd[N * 4];
pair<int, int> modi[N * 4];
int ed[N * 2][N * 2];
int main() {
  scanf("%*d%d", &n);
  int mc = 0;
  while (n--) {
    int x1, x2, y1, y2;
    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    xd[++xc] = x1;
    xd[++xc] = ++x2;
    yd[++yc] = y1;
    yd[++yc] = ++y2;
    modi[++mc] = make_pair(x1, y1);
    modi[++mc] = make_pair(-x1, -y2);
    modi[++mc] = make_pair(-x2, -y1);
    modi[++mc] = make_pair(x2, y2);
  }
  sort(xd + 1, xd + xc + 1);
  xc = unique(xd + 1, xd + xc + 1) - xd - 1;
  sort(yd + 1, yd + yc + 1);
  yc = unique(yd + 1, yd + yc + 1) - yd - 1;
  for (int i = 1; i <= mc; ++i) {
    int x, y;
    tie(x, y) = modi[i];
    int sgn = 1;
    if (x < 0) {
      sgn = -1;
      x = -x;
      y = -y;
    }
    x = lower_bound(xd + 1, xd + xc + 1, x) - xd;
    y = lower_bound(yd + 1, yd + yc + 1, y) - yd;
    ;
    ed[x][y] += sgn;
  }
  flow_graph<int> g(xc + yc + 2, (xc + 1) * (yc + 1));
  int S = 0, T = 1;
  for (int i = 1; i < xc; ++i) {
    g.link(S, i + 1, xd[i + 1] - xd[i]);
    ;
  };
  for (int i = 1; i < yc; ++i) {
    g.link(xc + i, T, yd[i + 1] - yd[i]);
    ;
  }
  for (int i = 1; i < xc; ++i)
    for (int j = 1; j < yc; ++j) {
      ed[i][j] += ed[i - 1][j] + ed[i][j - 1] - ed[i - 1][j - 1];
      if (ed[i][j]) {
        ;
        g.link(i + 1, xc + j, 1 << 30);
      }
    }
  printf("%d\n", g.max_flow(S, T));
  return 0;
}
