#include <bits/stdc++.h>
using namespace std;
struct Comparator {
  int operator()(int l, int r) const { return r < l; }
};
struct Vec;
long long INF = 1000 * 1000 * 1000 + 10;
bool way[(1000) * 2 + 10][(1000) * 2 + 10][2];
bool visited[(1000) * 2 + 10][(1000) * 2 + 10];
vector<long long> A((1000) + 10);
vector<long long> B((1000) + 10);
vector<long long> C((1000) + 10);
vector<long long> D((1000) + 10);
vector<long long> E((1000) + 10);
vector<long long> F((1000) + 10);
vector<long long> xar, yar;
int main() {
  cout.precision(15);
  cout << fixed;
  int N, M;
  cin >> N >> M;
  for (int(i) = 0; (i) < (N); ++(i)) {
    cin >> A[i] >> B[i] >> C[i];
  }
  for (int(i) = 0; (i) < (M); ++(i)) {
    cin >> D[i] >> E[i] >> F[i];
  }
  pair<long long, long long> sp;
  {
    map<long long, long long> Dict;
    vector<long long> CEF;
    for (int(i) = 0; (i) < (N); ++(i)) CEF.push_back(C[i]);
    for (int(i) = 0; (i) < (M); ++(i)) CEF.push_back(E[i]);
    for (int(i) = 0; (i) < (M); ++(i)) CEF.push_back(F[i]);
    CEF.push_back(0);
    sort(begin(CEF), end(CEF));
    Dict.insert({CEF[0], 0});
    xar.push_back(CEF[0]);
    int c = 0;
    for (int i = 1; i < CEF.size(); ++i) {
      if (CEF[i] != CEF[i - 1]) {
        c++;
        xar.push_back(CEF[i]);
      }
      Dict.insert({CEF[i], c});
    }
    for (int(i) = 0; (i) < (N); ++(i)) C[i] = Dict[C[i]];
    for (int(i) = 0; (i) < (M); ++(i)) E[i] = Dict[E[i]];
    for (int(i) = 0; (i) < (M); ++(i)) F[i] = Dict[F[i]];
    sp.first = Dict[0];
  }
  {
    map<long long, long long> Dict;
    vector<long long> CEF;
    for (int(i) = 0; (i) < (N); ++(i)) CEF.push_back(A[i]);
    for (int(i) = 0; (i) < (N); ++(i)) CEF.push_back(B[i]);
    for (int(i) = 0; (i) < (M); ++(i)) CEF.push_back(D[i]);
    CEF.push_back(0);
    sort(begin(CEF), end(CEF));
    Dict.insert({CEF[0], 0});
    yar.push_back(CEF[0]);
    int c = 0;
    for (int i = 1; i < CEF.size(); ++i) {
      if (CEF[i] != CEF[i - 1]) {
        c++;
        yar.push_back(CEF[i]);
      }
      Dict.insert({CEF[i], c});
    }
    for (int(i) = 0; (i) < (N); ++(i)) A[i] = Dict[A[i]];
    for (int(i) = 0; (i) < (N); ++(i)) B[i] = Dict[B[i]];
    for (int(i) = 0; (i) < (M); ++(i)) D[i] = Dict[D[i]];
    sp.second = Dict[0];
  }
  for (int(i) = 0; (i) < ((1000) * 2 + 10); ++(i))
    for (int(j) = 0; (j) < ((1000) * 2 + 10); ++(j))
      for (int(k) = 0; (k) < (2); ++(k)) way[i][j][k] = true;
  for (int(i) = 0; (i) < (N); ++(i)) {
    for (long long j = A[i] + 1; j <= B[i]; ++j) {
      way[C[i]][j][0] = false;
    }
  }
  for (int(i) = 0; (i) < (M); ++(i)) {
    for (long long j = E[i] + 1; j <= F[i]; ++j) {
      way[j][D[i]][1] = false;
    }
  }
  for (int(i) = 0; (i) < ((1000) * 2 + 10); ++(i))
    for (int(j) = 0; (j) < ((1000) * 2 + 10); ++(j)) visited[i][j] = false;
  stack<pair<long long, long long> > Q;
  Q.push(sp);
  visited[sp.first][sp.second] = true;
  while (!Q.empty()) {
    pair<long long, long long> cp = Q.top();
    Q.pop();
    vector<pair<long long, long long> > nps = {};
    if (cp.first < (1000) * 2 + 5 && way[cp.first][cp.second][0])
      nps.push_back({cp.first + 1, cp.second});
    if (cp.first > 0 && way[cp.first - 1][cp.second][0])
      nps.push_back({cp.first - 1, cp.second});
    if (cp.second < (1000) * 2 + 5 && way[cp.first][cp.second][1])
      nps.push_back({cp.first, cp.second + 1});
    if (cp.second > 0 && way[cp.first][cp.second - 1][1])
      nps.push_back({cp.first, cp.second - 1});
    for (pair<long long, long long> p : nps) {
      if (!visited[p.first][p.second]) {
        visited[p.first][p.second] = true;
        Q.push(p);
      }
    }
  }
  if (visited[0][0]) {
    cout << "INF" << endl;
    exit(0);
  }
  long long ans = 0;
  for (int(i) = 0; (i) < ((1000) * 2 + 10); ++(i)) {
    for (int(j) = 0; (j) < ((1000) * 2 + 10); ++(j)) {
      if (visited[i][j]) {
        ans += (xar[i] - xar[i - 1]) * (yar[j] - yar[j - 1]);
      }
    }
  }
  cout << ans << endl;
}
