#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T, class U>
using Pa = pair<T, U>;
template <class T>
using vec = vector<T>;
template <class T>
using vvec = vector<vec<T>>;
template <class T>
class Compress {
  int N;
  map<T, int> idx;
  map<int, T> value;
  vec<T> v;
  vec<T> cmp;

 public:
  Compress() {}
  void add(T x) { v.push_back(x); }
  void build() {
    for (auto &x : v) cmp.push_back(x);
    sort(cmp.begin(), cmp.end());
    cmp.erase(unique(cmp.begin(), cmp.end()), cmp.end());
    N = cmp.size();
    for (int i = 0; i < N; i++) idx[cmp[i]] = i;
  }
  int id(T val) { return idx[val]; }
  T val(int id) { return cmp[id]; }
  int size() { return N; }
};
class UnionFind {
 private:
  vec<int> p, s;
  vec<ll> val;
  int cnt;

 public:
  UnionFind() {}
  UnionFind(int N, vec<ll> v) : cnt(N), s(N, 1), p(N) {
    iota(p.begin(), p.end(), 0);
    val = v;
  }
  int find(int x) {
    if (p[x] == x)
      return x;
    else
      return p[x] = find(p[x]);
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (s[x] > s[y]) swap(x, y);
    p[x] = y;
    s[y] += s[x];
    val[y] += val[x];
    cnt--;
  }
  bool is_same_set(int x, int y) { return find(x) == find(y); }
  int size(int x) { return s[find(x)]; }
  int compnents_number() { return cnt; }
  ll getval(int x) { return val[find(x)]; }
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N, M;
  cin >> N >> M;
  Compress<int> cx, cy;
  vec<int> A(N), B(N), C(N), D(M), E(M), F(M);
  for (int i = 0; i < N; i++) {
    cin >> A[i] >> B[i] >> C[i];
    cy.add(C[i]);
    cx.add(A[i]), cx.add(B[i]);
  }
  for (int i = 0; i < M; i++) {
    cin >> D[i] >> E[i] >> F[i];
    cx.add(D[i]);
    cy.add(E[i]), cy.add(F[i]);
  }
  int inf = 1e9 + 1;
  cx.add(-inf), cx.add(inf);
  cy.add(-inf), cy.add(inf);
  cx.build(), cy.build();
  int H = cx.size(), W = cy.size();
  int sx = 0, sy = 0;
  for (int i = 0; i + 1 < H; i++)
    if (cx.val(i + 1) <= 0) sx = i;
  for (int j = 0; j + 1 < W; j++)
    if (cy.val(j + 1) <= 0) sy = j;
  vec<set<int>> noX(H), noY(W);
  for (int i = 0; i < N; i++) {
    int y = cy.id(C[i]), l = cx.id(A[i]), r = cx.id(B[i]);
    for (int j = l; j < r; j++) noY[y - 1].insert(j);
  }
  for (int i = 0; i < M; i++) {
    int x = cx.id(D[i]), l = cy.id(E[i]), r = cy.id(F[i]);
    for (int j = l; j < r; j++) noX[x - 1].insert(j);
  }
  vec<ll> v;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (i + 1 < H && j + 1 < W) {
        ll h = cx.val(i + 1) - cx.val(i), w = cy.val(j + 1) - cy.val(j);
        v.push_back(h * w);
      } else {
        v.push_back(0);
      }
    }
  UnionFind uf(H * W, v);
  auto id = [&](int i, int j) { return i * W + j; };
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (i + 1 < H && !noX[i].count(j)) uf.unite(id(i, j), id(i + 1, j));
      if (j + 1 < W && !noY[j].count(i)) uf.unite(id(i, j), id(i, j + 1));
    }
  for (auto x : {0, H - 1})
    for (auto y : {0, W - 1}) {
      if (uf.is_same_set(id(sx, sy), id(x, y))) {
        cout << "INF\n";
        return 0;
      }
    }
  cout << uf.getval(id(sx, sy)) << "\n";
}
