#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e18;
const long long MOD = 1e9 + 7;
const double EPS = 1e-8;
template <typename T>
T chmax(T& a, const T& b) {
  return a = (a > b ? a : b);
}
template <typename T>
T chmin(T& a, const T& b) {
  return a = (a < b ? a : b);
}
namespace std {
template <class S, class T>
ostream& operator<<(ostream& out, const pair<S, T>& a) {
  out << '(' << a.first << ", " << a.second << ')';
  return out;
}
}  // namespace std
struct UF {
  int n;
  int m;
  vector<int> d, r;
  UF(int n) : n(n), m(n), d(n, -1), r(n, 0){};
  int root(int i) {
    if (d[i] < 0) return i;
    return d[i] = root(d[i]);
  }
  bool same(int x, int y) { return root(x) == root(y); }
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) return false;
    if (r[x] < r[y])
      swap(x, y);
    else if (r[x] == r[y])
      r[x]++;
    d[x] += d[y];
    d[y] = x;
    --m;
    return true;
  }
  int size(int i) { return -d[root(i)]; }
  int size() { return m; }
};
int main() {
  int n, m;
  cin >> n >> m;
  vector<int> a(n), b(n), c(n), d(m), e(m), f(m);
  for (int i = (0); i < (int)(n); i++) cin >> a[i] >> b[i] >> c[i];
  for (int i = (0); i < (int)(m); i++) cin >> d[i] >> e[i] >> f[i];
  const int INF = 1e9 + 10;
  map<int, int> mx, my;
  mx[0] = 1;
  my[0] = 1;
  mx[-INF] = 1;
  mx[INF] = 1;
  mx[-INF - 1] = 1;
  mx[INF + 1] = 1;
  my[-INF] = 1;
  my[INF] = 1;
  my[-INF - 1] = 1;
  my[INF + 1] = 1;
  for (int i = (0); i < (int)(n); i++) {
    mx[a[i]] = 1;
    mx[b[i]] = 1;
    my[c[i]] = 1;
  }
  for (int i = (0); i < (int)(m); i++) {
    mx[d[i]] = 1;
    my[e[i]] = 1;
    my[f[i]] = 1;
  }
  {
    int cnt = 0;
    for (auto& p : mx) p.second = cnt++;
  }
  {
    int cnt = 0;
    for (auto& p : my) p.second = cnt++;
  }
  using B = bitset<4>;
  vector<vector<B>> nxt(my.size() - 1, vector<B>(mx.size() - 1));
  for (int i = (0); i < (int)(nxt.size()); i++)
    for (int j = (0); j < (int)(nxt[i].size()); j++) nxt[i][j].set();
  int dx[] = {-1, 0, 1, 0};
  int dy[] = {0, -1, 0, 1};
  for (int i = (0); i < (int)(n); i++) {
    auto y = my[c[i]];
    for (auto it = mx.lower_bound(a[i]); it->first != b[i]; ++it) {
      auto x = it->second;
      nxt[y - 1][x].reset(3);
      nxt[y][x].reset(1);
    }
  }
  for (int i = (0); i < (int)(m); i++) {
    auto x = mx[d[i]];
    for (auto it = my.lower_bound(e[i]); it->first != f[i]; ++it) {
      auto y = it->second;
      nxt[y][x - 1].reset(2);
      nxt[y][x].reset(0);
    }
  }
  const int sx = mx[-INF], tx = mx[INF];
  const int sy = my[-INF], ty = my[INF];
  vector<long long> rx(mx.size()), ry(my.size());
  for (auto&& p : mx) rx[p.second] = p.first;
  for (auto&& p : my) ry[p.second] = p.first;
  vector<vector<long long>> area(my.size() - 1,
                                 vector<long long>(mx.size() - 1));
  queue<pair<int, int>> q;
  q.push({my[0], mx[0]});
  while (!q.empty()) {
    auto p = q.front();
    q.pop();
    int y = p.first, x = p.second;
    if (y == sy || y == ty || x == sx || x == tx) {
      cout << "INF" << '\n';
      return 0;
    }
    { area[y][x] = (ry[y + 1] - ry[y]) * (rx[x + 1] - rx[x]); }
    for (int k = (0); k < (int)(4); k++)
      if (nxt[y][x][k]) {
        int ny = y + dy[k], nx = x + dx[k];
        if (area[ny][nx] == 0) q.push({ny, nx});
      }
  }
  long long ans = 0LL;
  for (auto&& low : area) ans += accumulate(low.begin(), low.end(), 0LL);
  cout << ans << '\n';
  return 0;
}
