#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()

template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) noexcept {
  return std::vector<T>(n, std::forward<T>(val));
}

template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) noexcept {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}

template<class T, class Cond>
struct chain {
  Cond cond; chain(Cond cond) : cond(cond) {}
  bool operator()(T& a, const T& b) const {
    if(cond(a, b)) { a = b; return true; }
    return false;
  }
};
template<class T, class Cond>
chain<T, Cond> make_chain(Cond cond) { return chain<T, Cond>(cond); }

#include <vector>
#include <tuple>

struct union_find {
  std::vector<int> par;
  union_find(int N): par(N, -1) {}
  int root(int x) {
    return par[x] < 0 ? x : par[x] = root(par[x]);
  }
  std::tuple<int, int> unite(int x, int y) {
    x = root(x);
    y = root(y);
    if(x == y) return { -1, -1 };
    if(par[x] > par[y]) std::swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return { x, y };
  }
  int size(int x) {
    return -par[root(x)];
  }
};

int main() {
  i64 N, M;
  cin >> N >> M;

  std::vector<i64> X, Y;
  X.push_back(1e18);
  X.push_back(-1e18);
  Y.push_back(1e18);
  Y.push_back(-1e18);
  X.push_back(0);
  Y.push_back(0);
  std::vector<i64> A(N), B(N), C(N);
  rep(i,0,N) {
    cin >> A[i] >> B[i] >> C[i];
    X.push_back(A[i]);
    X.push_back(B[i]);
    Y.push_back(C[i]);
  }
  std::vector<i64> D(M), E(M), F(M);
  rep(i,0,M) {
    cin >> D[i] >> E[i] >> F[i];
    X.push_back(D[i]);
    Y.push_back(E[i]);
    Y.push_back(F[i]);
  }
  sort(all(X));
  sort(all(Y));
  X.erase(unique(all(X)), end(X));
  Y.erase(unique(all(Y)), end(Y));
  std::vector<std::vector<int>> Yline(Y.size(), std::vector<int>(X.size()));
  std::vector<std::vector<int>> Xline(X.size(), std::vector<int>(Y.size()));
  auto index = [](const std::vector<i64>& A, i64 x) {
    return lower_bound(all(A), x) - begin(A);
  };
  rep(i,0,N) {
    i64 a = index(X, A[i]);
    i64 b = index(X, B[i]);
    i64 y = index(Y, C[i]);
    rep(j,a,b) {
      Yline[y][j] = true;
    }
  }
  rep(i,0,M) {
    i64 x = index(X, D[i]);
    i64 a = index(Y, E[i]);
    i64 b = index(Y, F[i]);
    rep(j,a,b) {
      Xline[x][j] = true;
    }
  }

  vector<i64> sz(X.size() * Y.size());
  i64 I = X.size();
  i64 J = Y.size();
  union_find uf(I * J);

  auto add = [](i64 a, i64 b) {
    if(a == -1) return -1ll;
    if(b == -1) return -1ll;
    return a + b;
  };

  rep(i,0,I) {
    rep(j,0,J) {

      if(i == 0 || j == 0 || i + 1 >= I - 1 || j + 1 >= J - 1) {
        sz[i * J + j] = -1;
      }
      else {
        sz[i * J + j] = (X[i + 1] - X[i]) * (Y[i + 1] - Y[i]);
      }
      //std::cout << sz[i * J + j] << " ";
    }
    //std::cout << endl;
  }
  rep(i,0,I ) {
    rep(j,0,J ) {
      if(0 < i && Xline[i][j] == false) {
        int r, c;
        std::tie(r, c) = uf.unite(i * J + j, (i - 1) * J + j);
        if(r != -1) {
          sz[r] = add(sz[r], sz[c]);
        }
      }
      if(i + 1 < I && Xline[i + 1][j] == false) {
        int r, c;
        std::tie(r, c) = uf.unite(i * J + j, (i + 1) * J + j);
        if(r != -1) {
          sz[r] = add(sz[r], sz[c]);
        }
      }
      if(0 < j && Yline[j][i] == false) {
        int r, c;
        std::tie(r, c) = uf.unite(i * J + j, i * J + (j - 1));
        if(r != -1) {
          sz[r] = add(sz[r], sz[c]);
        }
      }
      if(j + 1 < J && Yline[j + 1][i] == false) {
        int r, c;
        std::tie(r, c) = uf.unite(i * J + j, i * J + j + 1);
        if(r != -1) {
          sz[r] = add(sz[r], sz[c]);
        }
      }
    }
  }

  auto s = index(X, 0ll) * J + index(Y, 0ll);
  

  if(sz[uf.root(s)] == -1) {
    cout << "INF" << endl;
    assert(false);
  }
  else {
    cout << sz[uf.root(s)] << endl;
  }
}
