#include <bits/stdc++.h>
using namespace std;
map<long long, long long> zipx;
long long unzipx[2000];
long long inf = 1LL << 50;
long long compressx(vector<long long>& x) {
  sort(x.begin(), x.end());
  x.erase(unique(x.begin(), x.end()), x.end());
  for (long long i = 0; i < x.size(); i++) {
    zipx[x[i]] = i;
    unzipx[i] = x[i];
  }
  return x.size();
}
map<long long, long long> zipy;
long long unzipy[2000];
long long compressy(vector<long long>& x) {
  sort(x.begin(), x.end());
  x.erase(unique(x.begin(), x.end()), x.end());
  for (long long i = 0; i < x.size(); i++) {
    zipy[x[i]] = i;
    unzipy[i] = x[i];
  }
  return x.size();
}
template <typename T>
class Dinic {
 private:
  struct edge {
    long long to;
    T cap;
    long long rev;
  };
  long long V;
  vector<vector<edge> > G;
  vector<long long> level, iter;
  void bfs(long long s) {
    fill(level.begin(), level.end(), -1);
    queue<long long> que;
    level[s] = 0;
    que.push(s);
    while (!que.empty()) {
      long long v = que.front();
      que.pop();
      for (auto& e : G[v]) {
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[v] + 1;
          que.push(e.to);
        }
      }
    }
  }
  T dfs(long long v, long long t, T f) {
    if (v == t) {
      return f;
    }
    for (long long& i = iter[v]; i < (long long)G[v].size(); i++) {
      edge& e = G[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        T d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }

 public:
  Dinic(long long node_size) : V(node_size), G(V), level(V), iter(V) {}
  void add_edge(long long from, long long to, T cap) {
    G[from].push_back((edge){to, cap, (long long)G[to].size()});
    G[to].push_back((edge){from, (T)0, (long long)G[from].size() - 1});
  }
  T solve(long long s, long long t) {
    T flow = 0;
    for (;;) {
      bfs(s);
      if (level[t] < 0) return flow;
      fill(iter.begin(), iter.end(), 0);
      T f;
      while ((f = dfs(s, t, numeric_limits<T>::max())) > 0) {
        flow += f;
      }
    }
  }
};
signed main() {
  long long n, m;
  cin >> n >> m;
  vector<pair<long long, long long> > a;
  vector<pair<long long, long long> > b;
  vector<long long> x;
  vector<long long> y;
  for (long long i = 0; i < (long long)(m); ++i) {
    long long p, q, r, s;
    cin >> p >> q >> r >> s;
    a.push_back(make_pair(p, q));
    b.push_back(make_pair(r + 1, s + 1));
    x.push_back(p);
    y.push_back(q);
    x.push_back(r + 1);
    y.push_back(s + 1);
  }
  long long s = compressx(x);
  long long t = compressy(y);
  vector<vector<bool> > f(s + 10, vector<bool>(t + 10));
  for (long long i = 0; i < (long long)(m); ++i) {
    for (long long j = zipx[a[i].first]; j < zipx[b[i].first]; j++) {
      for (long long k = zipy[a[i].second]; k < zipy[b[i].second]; k++) {
        f[j][k] = 1;
      }
    }
  }
  Dinic<long long> dn(s + t + 2);
  long long S = s + t;
  long long T = s + t + 1;
  for (long long i = 0; i < (long long)(s - 1); ++i) {
    dn.add_edge(S, i, unzipx[i + 1] - unzipx[i]);
  }
  for (long long j = 0; j < (long long)(t - 1); ++j) {
    dn.add_edge(s + j, T, unzipy[j + 1] - unzipy[j]);
  }
  for (long long i = 0; i < (long long)(s); ++i) {
    for (long long j = 0; j < (long long)(t); ++j) {
      if (f[i][j]) {
        dn.add_edge(i, s + j, inf);
      }
    }
  }
  cout << dn.solve(S, T) << endl;
  return 0;
}
