#include <bits/stdc++.h>   struct MinCostFlow {     const long long INF1 = 1000000000LL;     const long long INF2 = 100000000LL;     struct edge {       long long u, v;       long long cap, cost;       edge* rev;       edge(const long long& uu, const long long& vv, const long long& _cap,            const long long& _cost, edge* _rev = nullptr)           : u(uu), v(vv), cap(_cap), cost(_cost), rev(_rev) {}     };     struct node {       long long id, d;       node(const long long& _id, const long long& _d) : id(_id), d(_d) {}       bool operator<(const node& o) const { return d < o.d; }       bool operator>(const node& o) const { return d > o.d; }     };     std::vector<std::vector<edge*>> adj;     long long s, t, mS, mT;     std::vector<edge*> prev;     std::vector<long long> w, pi;     MinCostFlow(long long n) {       s = n++;       t = n++;       mS = n++;       mT = n++;       adj.assign(n, std::vector<edge*>());     }     ~MinCostFlow(void) {       for (auto& row : adj)         for (auto& e : row) delete e;     }     edge* add_edge(const long long& a, const long long& b, const long long& cap,                    const long long& cost) {       edge* e1 = new edge(a, b, cap, cost);       edge* e2 = new edge(b, a, 0, -cost);       e1->rev = e2;       e2->rev = e1;       adj[a].push_back(e1);       adj[b].push_back(e2);       return e1;     }     std::pair<long long, long long> min_cost_max_flow(void) {       long long flow = 0;       long long cost = 0;       get_potential();       while (find_path()) {         flow += w[t];         cost += update();       }       return {flow, cost};     }     void get_potential(void) {       pi.assign(adj.size(), INF1);       pi[s] = 0;       for (long long i = 0; i + 1 < adj.size(); ++i) {         bool upd = false;         for (long long j = 0; j < adj.size(); ++j) {           for (edge* e : adj[j]) {             if (e->cap > 0 && pi[e->v] > pi[e->u] + e->cost) {               pi[e->v] = pi[e->u] + e->cost;               upd = true;             }           }         }         if (!upd) break;       }     }     bool find_path(void) {       std::vector<long long> d(adj.size(), INF1);       d[s] = 0;       prev.assign(adj.size(), nullptr);       w.assign(adj.size(), INF1);       std::priority_queue<node, std::vector<node>, std::greater<node>> pq;       pq.push({s, 0});       while (!pq.empty()) {         node best = pq.top();         pq.pop();         if (best.d != d[best.id]) continue;         for (edge* e : adj[best.id]) {           long long nd = d[best.id] + e->cost + pi[e->u] - pi[e->v];           if (e->cap > 0 && d[e->v] > nd) {             d[e->v] = nd;             prev[e->v] = e;             w[e->v] = std::min(w[best.id], e->cap);             pq.push({e->v, nd});           }         }       }       for (long long i = 0; i < pi.size(); ++i) pi[i] += d[i];       return d[t] < INF1;     }     long long update(void) {       long long v = t;       long long curr = 0;       while (prev[v] != nullptr) {         prev[v]->cap -= w[t];         prev[v]->rev->cap += w[t];         curr += w[t] * prev[v]->cost;         v = prev[v]->u;       }       return curr;     }   };   int main(void) {     std::ios::sync_with_stdio(false);     std::cin.tie(nullptr);     long long n, q;     std::cin >> n >> q;     std::vector<std::vector<char>> adj_mat(n, std::vector<char>(n, true));     for (long long type, l, r, v; q > 0; --q) {       std::cin >> type >> l >> r >> v;       --l;       --r;       --v;       if (type == 1) {         for (long long i = 0; i < v; ++i) {           for (long long j = l; j <= r; ++j) adj_mat[i][j] = false;         }       } else {         for (long long i = v + 1; i < n; ++i) {           for (long long j = l; j <= r; ++j) adj_mat[i][j] = false;         }       }     }     MinCostFlow graph(n + n);     for (long long num = 0; num < n; ++num) {       for (long long quant = 1, last = 0; quant <= n;            last = quant * quant, quant++) {         graph.add_edge(graph.s, num, 1, quant * quant - last);       }     }     for (long long spot = n; spot < 2 * n; ++spot)       graph.add_edge(spot, graph.t, 1, 0);     for (long long i = 0; i < n; ++i) {       for (long long j = 0; j < n; ++j) {         if (adj_mat[i][j]) graph.add_edge(i, n + j, 1, 0);       }     }     const std::pair<long long, long long> ret = graph.min_cost_max_flow();     if (ret.first != n) {       std::cout <<  -1 n ;     } else {       std::cout << ret.second <<   n ;     }     return 0;   }