#include <bits/stdc++.h>
using namespace std;
template <class n, class second>
ostream &operator<<(ostream &p, pair<n, second> x) {
  return p << "<" << x.first << ", " << x.second << ">";
}
template <class n>
auto operator<<(ostream &p, n y) ->
    typename enable_if<!is_same<n, string>::value,
                       decltype(y.begin(), p)>::type {
  int o = 0;
  p << "{";
  for (auto c : y) {
    if (o++) p << ", ";
    p << c;
  }
  return p << "}";
}
void dor() { cerr << '\n'; }
template <class n, class... second>
void dor(n p, second... y) {
  cerr << p << " ";
  dor(y...);
}
template <class n, class second>
void mini(n &p, second y) {
  if (p > y) p = y;
}
template <class n, class second>
void maxi(n &p, second y) {
  if (p < y) p = y;
}
long long INF = 6e18;
vector<pair<int, pair<int, int>>> V[2];
const int MXN = 1005;
pair<int, int> fu[MXN][MXN];
pair<int, int> find(pair<int, int> x) {
  return fu[x.first][x.second] == x
             ? x
             : fu[x.first][x.second] = find(fu[x.first][x.second]);
}
void unio(pair<int, int> x, pair<int, int> y) {
  x = find(x);
  y = find(y);
  fu[x.first][x.second] = y;
}
int n, m;
long long pole(int a, int b) {
  if (a == 0 || a == n) return INF * 1.1;
  if (b == 0 || b == m) return INF * 1.1;
  pair<int, int> s1 = {V[0][a - 1].first, V[0][a].first};
  pair<int, int> s2 = {V[1][b - 1].first, V[1][b].first};
  return ((long long)s1.second - s1.first) * ((long long)s2.second - s2.first);
}
pair<int, int> gdzie_lezy(int x, int y) {
  int xx = 0;
  while (xx < V[0].size() && x > V[0][xx].first) xx++;
  int yy = 0;
  while (yy < V[1].size() && y > V[1][yy].first) yy++;
  return {xx, yy};
}
bool connected_x(int x1, int y1, int x2, int y2) {
  if (y1 == 0 && y2 == 0) return 1;
  if (y1 == m && y2 == m) return 1;
  assert(y1 == y2);
  auto rozdziela = V[0][x1];
  pair<int, int> seg = {V[1][y1 - 1].first, V[1][y1].first};
  if (rozdziela.second.first <= seg.first &&
      seg.second <= rozdziela.second.second)
    return 0;
  return 1;
}
bool connected_y(int x1, int y1, int x2, int y2) {
  if (x1 == 0 && x2 == 0) return 1;
  if (x1 == n && x2 == n) return 1;
  assert(x1 == x2);
  auto rozdziela = V[1][y1];
  pair<int, int> seg = {V[0][x1 - 1].first, V[0][x1].first};
  if (rozdziela.second.first <= seg.first &&
      seg.second <= rozdziela.second.second)
    return 0;
  return 1;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 0; i < (int)(n); ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    V[0].push_back(make_pair(c, make_pair(a, b)));
  }
  for (int i = 0; i < (int)(m); ++i) {
    int a, b, c;
    cin >> c >> a >> b;
    V[1].push_back(make_pair(c, make_pair(a, b)));
  }
  for (int i = 0; i < (int)(n + 1); ++i)
    for (int j = 0; j < (int)(m + 1); ++j) fu[i][j] = {i, j};
  sort((V[0]).begin(), (V[0]).end());
  sort((V[1]).begin(), (V[1]).end());
  for (int i = (0); i <= (int)(n - 1); ++i)
    for (int j = (1); j <= (int)(m); ++j) {
      if (connected_x(i, j, i + 1, j)) {
        unio({i, j}, {i + 1, j});
      }
    }
  for (int i = (1); i <= (int)(n); ++i)
    for (int j = (0); j <= (int)(m - 1); ++j) {
      if (connected_y(i, j, i, j + 1)) {
        unio({i, j}, {i, j + 1});
      }
    }
  pair<int, int> kro = gdzie_lezy(0, 0);
  pair<int, int> spojna = find(kro);
  long long sum = 0;
  for (int i = 0; i < (int)(n + 1); ++i)
    for (int j = 0; j < (int)(m + 1); ++j) {
      if (find({i, j}) == spojna) {
        long long res = pole(i, j);
        if (res >= INF) {
          puts("INF");
          return 0;
        }
        sum += res;
      }
    }
  cout << sum << '\n';
}
