#include <bits/stdc++.h>
using namespace std;
template <class X, class Y>
bool minimize(X &x, const Y &y) {
  X eps = 1e-9;
  if (x > y + eps) {
    x = y;
    return true;
  } else
    return false;
}
template <class X, class Y>
bool maximize(X &x, const Y &y) {
  X eps = 1e-9;
  if (x + eps < y) {
    x = y;
    return true;
  } else
    return false;
}
template <class T>
T Abs(const T &x) {
  return (x < 0 ? -x : x);
}
const long long INF = (long long)1e18 + 7LL;
struct DinicFlow {
  int numNode, numEdge;
  vector<int> dist, head, work;
  vector<int> point, ___next;
  vector<long long> flow, capa;
  DinicFlow(int n = 0) {
    numNode = n;
    numEdge = 0;
    dist.assign(n + 7, 0);
    head.assign(n + 7, -1);
    work.assign(n + 7, 0);
  }
  int addEdge(int u, int v, long long c1, long long c2 = 0) {
    int ret = numEdge;
    point.push_back(v);
    capa.push_back(c1);
    flow.push_back(0);
    ___next.push_back(head[u]);
    head[u] = numEdge++;
    point.push_back(u);
    capa.push_back(c2);
    flow.push_back(0);
    ___next.push_back(head[v]);
    head[v] = numEdge++;
    return ret;
  }
  bool bfs(int s, int t) {
    queue<int> q;
    for (int i = 1; i <= numNode; i++) dist[i] = -1;
    dist[s] = 0;
    q.push(s);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (int i = head[u]; i >= 0; i = ___next[i])
        if (flow[i] < capa[i] && dist[point[i]] < 0) {
          dist[point[i]] = dist[u] + 1;
          q.push(point[i]);
        }
    }
    return dist[t] >= 0;
  }
  long long dfs(int s, int t, long long f) {
    if (s == t) return f;
    for (int &i = work[s]; i >= 0; i = ___next[i])
      if (flow[i] < capa[i] && dist[point[i]] == dist[s] + 1) {
        int d = dfs(point[i], t, min(f, capa[i] - flow[i]));
        if (d > 0) {
          flow[i] += d;
          flow[i ^ 1] -= d;
          return d;
        }
      }
    return 0;
  }
  long long maxFlow(int s, int t) {
    long long totFlow = 0;
    while (bfs(s, t)) {
      for (int i = 1; i <= numNode; i++) work[i] = head[i];
      while (true) {
        long long d = dfs(s, t, INF);
        if (d == 0) break;
        totFlow += d;
      }
    }
    return totFlow;
  }
  int getFlow(int id) const { return flow[id]; }
};
struct Area {
  int x1, y1, x2, y2;
  Area() { x1 = y1 = x2 = y2 = 0; }
  Area(int _x1, int _y1, int _x2, int _y2) {
    x1 = _x1;
    y1 = _y1;
    x2 = _x2;
    y2 = _y2;
  }
};
vector<int> rows, cols;
bool mark[1111][1111];
int n, numArea, numRow, numCol;
Area areas[1111];
void init(void) {
  cin >> n >> numArea;
  for (int i = (1), _b = (numArea); i <= _b; i++) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    areas[i] = Area(x1, y1, x2, y2);
    rows.push_back(x1);
    rows.push_back(x2 + 1);
    cols.push_back(y1);
    cols.push_back(y2 + 1);
  }
  rows.push_back(1);
  cols.push_back(1);
  rows.push_back(n + 1);
  cols.push_back(n + 1);
  sort((rows).begin(), (rows).end());
  rows.resize(unique((rows).begin(), (rows).end()) - rows.begin());
  sort((cols).begin(), (cols).end());
  cols.resize(unique((cols).begin(), (cols).end()) - cols.begin());
  numRow = rows.size() - 1;
  numCol = cols.size() - 1;
  for (int i = (1), _b = (numArea); i <= _b; i++) {
    int r1 = lower_bound((rows).begin(), (rows).end(), areas[i].x1) -
             rows.begin() + 1;
    int r2 =
        upper_bound((rows).begin(), (rows).end(), areas[i].x2) - rows.begin();
    int c1 = lower_bound((cols).begin(), (cols).end(), areas[i].y1) -
             cols.begin() + 1;
    int c2 =
        upper_bound((cols).begin(), (cols).end(), areas[i].y2) - cols.begin();
    for (int j = (r1), _b = (r2); j <= _b; j++)
      for (int k = (c1), _b = (c2); k <= _b; k++) mark[j][k] = true;
  }
}
void process(void) {
  DinicFlow df(numRow + numCol + 2);
  int src = numRow + numCol + 1;
  int snk = numRow + numCol + 2;
  for (int i = (1), _b = (numRow); i <= _b; i++)
    df.addEdge(src, i, rows[i] - rows[i - 1]);
  for (int i = (1), _b = (numCol); i <= _b; i++)
    df.addEdge(i + numRow, snk, cols[i] - cols[i - 1]);
  for (int i = (1), _b = (numRow); i <= _b; i++)
    for (int j = (1), _b = (numCol); j <= _b; j++)
      if (mark[i][j]) df.addEdge(i, j + numRow, INF);
  cout << df.maxFlow(src, snk) << endl;
}
int main(void) {
  init();
  process();
  return 0;
}
