#include <algorithm>
#include <array>
#include <iomanip>
#include <iostream>
#include <queue>
#include <vector>

const std::array<int32_t, 4> dx({-1, 0, 1, 0});
const std::array<int32_t, 4> dy({0, -1, 0, 1});

inline uint32_t id(const std::vector<int32_t>& coord, int32_t target) {
  return std::lower_bound(coord.begin(), coord.end(), target) - coord.begin();
}

int main() {
  uint32_t N = 0, M = 0;
  std::cin >> N >> M;
  std::vector<int32_t> A(N), B(N), C(N);
  for (size_t n = 0; n < N; n++) std::cin >> A[n] >> B[n] >> C[n];
  std::vector<int32_t> D(M), E(M), F(M);
  for (size_t m = 0; m < M; m++) std::cin >> D[m] >> E[m] >> F[m];

  // coordinate compression
  std::vector<int32_t> x_mesh(A);
  x_mesh.insert(x_mesh.end(), B.begin(), B.end());
  x_mesh.insert(x_mesh.end(), D.begin(), D.end());
  x_mesh.push_back(0);
  std::vector<int32_t> y_mesh(C);
  y_mesh.insert(y_mesh.end(), E.begin(), E.end());
  y_mesh.insert(y_mesh.end(), F.begin(), F.end());
  y_mesh.push_back(0);

  std::sort(x_mesh.begin(), x_mesh.end());
  std::sort(y_mesh.begin(), y_mesh.end());

  x_mesh.erase(std::unique(x_mesh.begin(), x_mesh.end()), x_mesh.end());
  y_mesh.erase(std::unique(y_mesh.begin(), y_mesh.end()), y_mesh.end());

  // gen grid
  std::vector<std::vector<int32_t>> grid(
      x_mesh.size() * 2, std::vector<int32_t>(y_mesh.size() * 2, 0));
  for (size_t n = 0; n < N; n++) {
    uint32_t A_id = id(x_mesh, A[n]), B_id = id(x_mesh, B[n]),
             C_id = id(y_mesh, C[n]);
    for (size_t i = A_id * 2; i <= B_id * 2; i++) grid[i][C_id * 2] = -1;
  }
  for (size_t m = 0; m < M; m++) {
    uint32_t D_id = id(x_mesh, D[m]), E_id = id(y_mesh, E[m]),
             F_id = id(y_mesh, F[m]);
    for (size_t i = E_id * 2; i <= F_id * 2; i++) grid[D_id * 2][i] = -1;
  }

  // bfs
  bool INF = false;
  uint64_t sum = 0;
  std::queue<std::pair<int32_t, int32_t>> Q;
  Q.push({id(x_mesh, 0) * 2, id(y_mesh, 0) * 2});
  while (!Q.empty()) {
    int32_t x = Q.front().first, y = Q.front().second;
    Q.pop();

    if (grid[x][y] != 0) continue;
    grid[x][y] = 1;

    // grid edge
    if (x == 0 || x == static_cast<int32_t>(grid.size()) - 1 || y == 0 ||
        y == static_cast<int32_t>(grid[0].size()) - 1) {
      INF = true;
      break;
    }

    // current area
    if (x % 2 && y % 2)
      sum += static_cast<uint64_t>(x_mesh[x / 2 + 1] - x_mesh[x / 2]) *
             static_cast<uint64_t>(y_mesh[y / 2 + 1] - y_mesh[y / 2]);

    // next area
    for (size_t i = 0; i < dx.size(); i++) Q.push({x + dx[i], y + dy[i]});
  }

  if (INF)
    std::cout << "INF" << std::endl;
  else
    std::cout << sum << std::endl;

  return 0;
}