#include <bits/stdc++.h>   using namespace std;   long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }   const int MAXN = 10000;   const int MAXBLOCKS = 10000;   const int MAXRECT = 4 * MAXBLOCKS;   const int MAXGN = 2 + 4 * MAXN + MAXRECT;   const int MAXGM = 6 * MAXN + 2 * 2 * 14 * MAXRECT;   typedef struct R {     int lx, ly, hx, hy;   } R;   int n, h, w;   R b[MAXBLOCKS];   int nb;   bool blocked[MAXN][MAXN];   R r[MAXRECT];   int nr;   typedef struct MF {     int n, m;     int ghead[MAXGN], gnxt[2 * MAXGM], gto[2 * MAXGM], gcap[2 * MAXGM];     void init(int _n) {       n = _n, m = 0;       for (int i = (0); i < (n); ++i) ghead[i] = -1;     }     void addedge(int a, int b, int c) {       gnxt[2 * m + 0] = ghead[a], ghead[a] = 2 * m + 0, gto[2 * m + 0] = b,                    gcap[2 * m + 0] = c;       gnxt[2 * m + 1] = ghead[b], ghead[b] = 2 * m + 1, gto[2 * m + 1] = a,                    gcap[2 * m + 1] = 0;       ++m;     }     int d[MAXGN];     int q[MAXGN], qhead, qtail;     int cur[MAXGN];     int dinic(int s, int t) {       int ret = 0;       int niter = 0;       while (true) {         for (int i = (0); i < (n); ++i) d[i] = INT_MAX;         qhead = qtail = 0;         d[s] = 0, q[qhead++] = s;         while (qtail < qhead && d[t] == INT_MAX) {           int at = q[qtail++];           for (int x = ghead[at]; x != -1; x = gnxt[x]) {             int to = gto[x];             if (gcap[x] == 0 || d[to] != INT_MAX) continue;             d[to] = d[at] + 1;             q[qhead++] = to;           }         }         if (d[t] == INT_MAX) {           return ret;         }         for (int i = (0); i < (n); ++i) cur[i] = ghead[i];         ret += dfs(s, t, INT_MAX);         ++niter;       }     }     int dfs(int at, int t, int rem) {       int ret = 0;       if (at == t) return rem;       if (d[at] >= d[t]) return 0;       for (; cur[at] != -1; cur[at] = gnxt[cur[at]]) {         int to = gto[cur[at]], cap = gcap[cur[at]];         if (d[to] != d[at] + 1 || cap == 0) continue;         int now = dfs(to, t, min(cap, rem));         rem -= now;         ret += now;         gcap[cur[at]] -= now;         gcap[cur[at] ^ 1] += now;         if (rem == 0) return ret;       }       return ret;     }     void print() {       for (int i = (0); i < (m); ++i)         if (gcap[2 * i + 0] == 0)           printf( used %d->%d n , gto[2 * i + 1], gto[2 * i + 0]);     }   } MF;   MF g;   int solve() {     memset(blocked, false, sizeof(blocked));     h = w = n;     for (int i = (0); i < (nb); ++i)       for (int x = (b[i].lx); x <= (b[i].hx); ++x)         for (int y = (b[i].ly); y <= (b[i].hy); ++y) blocked[x][y] = true;     nr = 0;     for (int lx = (0); lx < (h); ++lx)       for (int ly = (0); ly < (w); ++ly)         if (!blocked[lx][ly]) {           int hy = ly;           while (hy + 1 < w && !blocked[lx][hy + 1]) ++hy;           int hx = lx;           while (hx + 1 < h) {             bool ok = true;             for (int y = (ly); y <= (hy); ++y)               if (blocked[hx + 1][y]) {                 ok = false;                 break;               }             if (!ok)               break;             else               ++hx;           }           r[nr].lx = lx, r[nr].ly = ly, r[nr].hx = hx, r[nr].hy = hy, ++nr;           for (int x = (lx); x <= (hx); ++x)             for (int y = (ly); y <= (hy); ++y) blocked[x][y] = true;         }     g.init(2 + 4 * n + nr);     for (int i = (0); i < (n); ++i) g.addedge(0, 2 + n + i, 1);     for (int i = (1); i < (n); ++i)       g.addedge(2 + 2 * i, 2 + i, n), g.addedge(2 + 2 * i + 1, 2 + i, n);     for (int i = (0); i < (n); ++i) g.addedge(2 + 3 * n + i, 1, 1);     for (int i = (1); i < (n); ++i)       g.addedge(2 + 2 * n + i, 2 + 2 * n + 2 * i, n),           g.addedge(2 + 2 * n + i, 2 + 2 * n + 2 * i + 1, n);     for (int i = (0); i < (nr); ++i) {       {         int lidx = n + r[i].lx, ridx = n + r[i].hx + 1;         for (; lidx < ridx; lidx >>= 1, ridx >>= 1) {           if (lidx & 1) g.addedge(2 + lidx, 2 + 4 * n + i, n), ++lidx;           if (ridx & 1) --ridx, g.addedge(2 + ridx, 2 + 4 * n + i, n);         }       }       {         int lidx = n + r[i].ly, ridx = n + r[i].hy + 1;         for (; lidx < ridx; lidx >>= 1, ridx >>= 1) {           if (lidx & 1) g.addedge(2 + 4 * n + i, 2 + 2 * n + lidx, n), ++lidx;           if (ridx & 1) --ridx, g.addedge(2 + 4 * n + i, 2 + 2 * n + ridx, n);         }       }     }     int ret = g.dinic(0, 1);     return ret;   }   void run() {     scanf( %d , &n);     scanf( %d , &nb);     for (int i = (0); i < (nb); ++i) {       int lx, ly, hx, hy;       scanf( %d%d%d%d , &b[i].lx, &b[i].ly, &b[i].hx, &b[i].hy);       --b[i].lx, --b[i].ly, --b[i].hx, --b[i].hy;     }     printf( %d n , solve());   }   void stress() {     n = MAXN;     nb = MAXBLOCKS - 1;     for (int i = (0); i < (nb); ++i) {       b[i].lx = i, b[i].hx = i, b[i].ly = (rand() * 1000 + rand()) % n,       b[i].hy = n - 1;     }     clock_t begin = clock();     printf( %d n , solve());     clock_t end = clock();     printf( %.9lf n , (double)(end - begin) / CLOCKS_PER_SEC);   }   int main() {     run();     return 0;   }