#include <bits/stdc++.h>   using namespace std;   const int MAXN = 3005, MAXM = 55;   const double inf = 1e9 + 5;   vector<int> graph[MAXN];   double c[MAXN][MAXN];   int f[MAXN][MAXN];   priority_queue<pair<double, int> > q;   double dist[MAXN];   int last[MAXN];   int n, Q;   int upperBound[MAXM], lowerBound[MAXM];   int arrayNode[MAXM];   int dispenserNode[MAXM][MAXM];   int startNode[MAXM], endNode[MAXM];   int S = 3001, T = 3002;   void addEdge(int u, int v, int flow, double cost) {     graph[u].push_back(v);     graph[v].push_back(u);     f[u][v] = flow;     c[u][v] = cost;     c[v][u] = cost;   }   double Dijkstra(int s, int t) {     for (int i = 0; i < MAXN; i++) {       dist[i] = inf;     }     dist[s] = 0;     int u;     q.push({0, s});     while (q.empty() == false) {       u = q.top().second;       q.pop();       for (int i = 0; i < graph[u].size(); i++) {         if (f[u][graph[u][i]] != 0 &&             dist[graph[u][i]] > dist[u] + c[u][graph[u][i]]) {           dist[graph[u][i]] = dist[u] + c[u][graph[u][i]];           last[graph[u][i]] = u;           q.push({-dist[graph[u][i]], graph[u][i]});         }       }     }     return dist[t];   }   pair<int, double> minCostMaxFlow(int s, int t) {     int maxFlow = 0;     double minCost = 0;     while (true) {       double cost = Dijkstra(s, t);       if (cost == inf) break;       int u = t;       int flow = inf;       while (u != s) {         flow = min(flow, f[last[u]][u]);         u = last[u];       }       u = t;       while (u != s) {         f[last[u]][u] -= flow;         f[u][last[u]] += flow;         u = last[u];       }       maxFlow += flow;       minCost += cost * flow;     }     return {maxFlow, minCost};   }   int main() {     ios::sync_with_stdio(false);     cin.tie(NULL);     cin >> n >> Q;     for (int i = 1; i <= n; i++) {       lowerBound[i] = 1;       upperBound[i] = n;     }     while (Q--) {       int type;       int l, r, v;       cin >> type;       cin >> l >> r >> v;       if (type == 1) {         for (int i = l; i <= r; i++) {           lowerBound[i] = max(lowerBound[i], v);         }       } else {         for (int i = l; i <= r; i++) {           upperBound[i] = min(upperBound[i], v);         }       }     }     for (int i = 1; i <= n; i++) {       if (lowerBound[i] > upperBound[i]) {         cout <<  -1  <<   n ;         return 0;       }     }     int node = 1;     for (int i = 1; i <= n; i++) {       startNode[i] = node;       node++;     }     for (int i = 1; i <= n; i++) {       endNode[i] = node;       node++;     }     for (int i = 1; i <= n; i++) {       arrayNode[i] = node;       node++;     }     for (int i = 1; i <= n; i++) {       for (int j = 1; j <= n; j++) {         dispenserNode[i][j] = node;         node++;       }     }     for (int i = 1; i <= n; i++) {       addEdge(S, startNode[i], n, 0);     }     for (int i = 1; i <= n; i++) {       int value = 1, sum = 0;       for (int j = 1; j <= n; j++) {         addEdge(startNode[i], dispenserNode[i][j], 1, j * j - sum);         addEdge(dispenserNode[i][j], endNode[i], 1, 0);         sum += j * j - sum;       }     }     for (int i = 1; i <= n; i++) {       for (int j = 1; j <= n; j++) {         if (i >= lowerBound[j] && i <= upperBound[j]) {           addEdge(endNode[i], arrayNode[j], 1, 0);         }       }     }     for (int i = 1; i <= n; i++) {       addEdge(arrayNode[i], T, 1, 0);     }     cout << minCostMaxFlow(S, T).second <<   n ;   }