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