#include <bits/stdc++.h>
const int INF = 200000005;
const long long INFLL = 1000000000000000008ll;
const long long MOD = 1000000007;
using namespace std;
struct NetworkFlowWithCost {
  struct edge {
    int a, b, cap, cost;
    edge(int p1, int p2, int p3, int p4) : a(p1), b(p2), cap(p3), cost(p4){};
  };
  const int INF = 2147483647;
  int s, t;
  vector<edge> edges;
  vector<int> best, from;
  vector<vector<int>> e;
  NetworkFlowWithCost(int sz) {
    best.resize(sz + 1);
    e.resize(sz + 1);
    from.resize(sz + 1);
  }
  void setSource(int n) { s = n; }
  void setSink(int n) { t = n; }
  void addEdge(int a, int b, int _cap, int _cost) {
    edges.push_back(edge(a, b, _cap, _cost));
    e[a].push_back(((int)edges.size()) - 1);
    edges.push_back(edge(b, a, 0, -_cost));
    e[b].push_back(((int)edges.size()) - 1);
  }
  bool dijkstra() {
    fill(best.begin(), best.end(), INF);
    priority_queue<pair<int, int>, vector<pair<int, int>>,
                   greater<pair<int, int>>>
        q;
    best[s] = 0, q.push({0, s});
    while (!q.empty()) {
      pair<int, int> p = q.top();
      q.pop();
      int n = p.second, c = p.first;
      if (best[n] < c) continue;
      if (n == t) return true;
      for (int idx : e[n]) {
        edge &ed = edges[idx];
        if (ed.cap && c + ed.cost < best[ed.b]) {
          best[ed.b] = c + ed.cost;
          from[ed.b] = idx;
          q.push({best[ed.b], ed.b});
        }
      }
    }
    return best[t] < INF;
  }
  int minCostMaxFlow() {
    int c = 0;
    while (dijkstra()) {
      int ff = INF, n = t, prev = c;
      while (n != s) {
        edge &ed = edges[from[n]];
        c += ed.cost;
        ff = min(ff, ed.cap);
        n = ed.a;
      }
      n = t;
      while (n != s) {
        edge &ed = edges[from[n]];
        edge &rev = from[n] % 2 ? edges[from[n] - 1] : edges[from[n] + 1];
        ed.cap -= ff, rev.cap += ff;
        n = ed.a;
      }
    }
    return c;
  }
};
int Low[55], High[55], N, M;
int main() {
  cin >> N >> M;
  for (int i = (1); i <= (N); i++) Low[i] = 1, High[i] = N;
  for (int i = (1); i <= (M); i++) {
    int t, l, r, v;
    scanf("%d %d %d %d", &t, &l, &r, &v);
    if (t == 1)
      for (int i = (l); i <= (r); i++) Low[i] = max(Low[i], v);
    if (t == 2)
      for (int i = (l); i <= (r); i++) High[i] = min(High[i], v);
  }
  for (int i = (1); i <= (N); i++)
    if (Low[i] > High[i]) {
      cout << -1;
      return 0;
    }
  NetworkFlowWithCost g(2 * N + 4);
  int s = 0, t = 2 * N + 1;
  g.setSink(2 * N + 1);
  g.setSource(0);
  for (int i = (1); i <= (N); i++) g.addEdge(s, i, 1, 0);
  for (int i = (1); i <= (N); i++)
    for (int j = (Low[i] + N); j <= (High[i] + N); j++) g.addEdge(i, j, 1, 0);
  for (int i = (N + 1); i <= (2 * N); i++)
    for (int j = (0); j <= (N); j++) g.addEdge(i, t, 1, 2 * j + 1);
  cout << g.minCostMaxFlow();
}
