#include <bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
using namespace std;
template <class T>
inline T bigmod(T p, T e, T M) {
  long long ret = 1;
  for (; e > 0; e >>= 1) {
    if (e & 1) ret = (ret * p) % M;
    p = (p * p) % M;
  }
  return (T)ret;
}
template <class T>
inline T gcd(T a, T b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}
template <class T>
inline T modinverse(T a, T M) {
  return bigmod(a, M - 2, M);
}
template <class T>
inline T lcm(T a, T b) {
  a = abs(a);
  b = abs(b);
  return (a / gcd(a, b)) * b;
}
template <class T, class X>
inline bool getbit(T a, X i) {
  T t = 1;
  return ((a & (t << i)) > 0);
}
template <class T, class X>
inline T setbit(T a, X i) {
  T t = 1;
  return (a | (t << i));
}
template <class T, class X>
inline T resetbit(T a, X i) {
  T t = 1;
  return (a & (~(t << i)));
}
inline long long getnum() {
  char c = getchar();
  long long num, sign = 1;
  for (; c < '0' || c > '9'; c = getchar())
    if (c == '-') sign = -1;
  for (num = 0; c >= '0' && c <= '9';) {
    c -= '0';
    num = num * 10 + c;
    c = getchar();
  }
  return num * sign;
}
inline long long power(long long a, long long b) {
  long long multiply = 1;
  for (int i = (0); i < (b); i++) {
    multiply *= a;
  }
  return multiply;
}
struct Edge {
  int u, v;
  long long cap, cost;
  Edge(int _u, int _v, long long _cap, long long _cost) {
    u = _u;
    v = _v;
    cap = _cap;
    cost = _cost;
  }
};
struct MinCostFlow {
  int n, s, t;
  long long flow, cost;
  vector<vector<int> > graph;
  vector<Edge> e;
  vector<long long> dist;
  vector<int> parent;
  MinCostFlow(int _n) {
    n = _n;
    graph.assign(n, vector<int>());
  }
  void addEdge(int u, int v, long long cap, long long cost,
               bool directed = true) {
    graph[u].push_back(e.size());
    e.push_back(Edge(u, v, cap, cost));
    graph[v].push_back(e.size());
    e.push_back(Edge(v, u, 0, -cost));
    if (!directed) addEdge(v, u, cap, cost, true);
  }
  pair<long long, long long> getMinCostFlow(int _s, int _t) {
    s = _s;
    t = _t;
    flow = 0, cost = 0;
    while (SPFA()) {
      flow += sendFlow(t, 1LL << 62);
    }
    return make_pair(flow, cost);
  }
  bool SPFA() {
    parent.assign(n, -1);
    dist.assign(n, 1LL << 62);
    dist[s] = 0;
    vector<int> queuetime(n, 0);
    queuetime[s] = 1;
    vector<bool> inqueue(n, 0);
    inqueue[s] = true;
    queue<int> q;
    q.push(s);
    bool negativecycle = false;
    while (!q.empty() && !negativecycle) {
      int u = q.front();
      q.pop();
      inqueue[u] = false;
      for (int i = 0; i < graph[u].size(); i++) {
        int eIdx = graph[u][i];
        int v = e[eIdx].v;
        long long w = e[eIdx].cost, cap = e[eIdx].cap;
        if (dist[u] + w < dist[v] && cap > 0) {
          dist[v] = dist[u] + w;
          parent[v] = eIdx;
          if (!inqueue[v]) {
            q.push(v);
            queuetime[v]++;
            inqueue[v] = true;
            if (queuetime[v] == n + 2) {
              negativecycle = true;
              break;
            }
          }
        }
      }
    }
    return dist[t] != (1LL << 62);
  }
  long long sendFlow(int v, long long curFlow) {
    if (parent[v] == -1) return curFlow;
    int eIdx = parent[v];
    int u = e[eIdx].u;
    long long w = e[eIdx].cost;
    long long f = sendFlow(u, min(curFlow, e[eIdx].cap));
    cost += f * w;
    e[eIdx].cap -= f;
    e[eIdx ^ 1].cap += f;
    return f;
  }
};
int n, q, t[102], l[102], r[102], v[102];
vector<pair<int, int> > ranges;
vector<int> take[52][3];
int main() {
  int test, cases = 1;
  cin >> n >> q;
  MinCostFlow network(2 * n + 5);
  int src = 0, sink = 2 * n + 1;
  for (int i = (0); i < (q); i++) {
    cin >> t[i] >> l[i] >> r[i] >> v[i];
    for (int j = (l[i]); j < (r[i] + 1); j++) {
      take[j][t[i]].push_back(v[i]);
    }
  }
  for (int i = (1); i < (n + 1); i++) {
    network.addEdge(src, i, 1, 0);
    if (take[i][1].empty() && take[i][2].empty()) {
      for (int j = 1; j <= n; j++) {
        network.addEdge(i, j + n, 1, 0);
      }
    } else if (!take[i][1].empty() && take[i][2].empty()) {
      sort(take[i][1].begin(), take[i][1].end());
      for (int j = take[i][1].back(); j <= n; j++) {
        network.addEdge(i, j + n, 1, 0);
      }
    } else if (!take[i][2].empty() && take[i][1].empty()) {
      sort(take[i][2].begin(), take[i][2].end());
      for (int j = 1; j <= take[i][2][0]; j++) {
        network.addEdge(i, j + n, 1, 0);
      }
    } else {
      sort(take[i][1].begin(), take[i][1].end());
      sort(take[i][2].begin(), take[i][2].end());
      take[i][1].erase(unique(take[i][1].begin(), take[i][1].end()),
                       take[i][1].end());
      take[i][2].erase(unique(take[i][2].begin(), take[i][2].end()),
                       take[i][2].end());
      int x = take[i][1].back();
      int y = take[i][2][0];
      if (x > y) {
        cout << "-1"
             << "\n";
        return 0;
      } else {
        for (int j = x; j <= y; j++) {
          network.addEdge(i, j + n, 1, 0);
        }
      }
    }
  }
  for (int i = (1); i < (n + 1); i++) {
    for (int j = (1); j < (n + 1); j++) {
      network.addEdge(i + n, sink, 1, 2 * j - 1);
    }
  }
  pair<int, int> out = network.getMinCostFlow(src, sink);
  cout << out.second << "\n";
  return 0;
}
