#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;   }