#include <bits/stdc++.h>
#define REP(i, n) for (decltype(n) i = 0; i < (n); ++i)
using namespace std;
using i64 = long long;
using u64 = unsigned long long;

int N, M;
i64 INF = 1LL << 60;

optional<i64> bfs(const vector<i64>& xv, const vector<i64>& yv,
                  const vector<vector<bool>>& adj) {
  int x0 = lower_bound(xv.begin(), xv.end(), 0) - xv.begin();
  int y0 = lower_bound(yv.begin(), yv.end(), 0) - yv.begin();

  i64 area = 0;
  deque<tuple<int, int>> que;
  que.emplace_back(x0, y0);
  que.emplace_back(x0 - 1, y0);
  que.emplace_back(x0, y0 - 1);
  que.emplace_back(x0 - 1, y0 - 1);

  int width = yv.size();
  vector<bool> visited(xv.size() * width);
  vector<tuple<int, int>> steps{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
  while (que.size()) {
    auto [x, y] = que.front();
    que.pop_front();
    if (visited[x * width + y]) {
      continue;
    }
    visited[x * width + y] = true;

    if (xv[x + 1] == INF || xv[x] == -INF || yv[y + 1] == INF ||
        yv[y] == -INF) {
      return nullopt;
    }
    area += (xv[x + 1] - xv[x]) * (yv[y + 1] - yv[y]);
    auto& curadj = adj[x * width + y];
    for (auto [dx, dy] : steps) {
      if (x + dx < 0 || x + dx >= int(xv.size()) - 1 || y + dy < 0 ||
          y + dy >= int(yv.size()) - 1) {
        continue;
      }
      int nxt = (x + dx) * width + y + dy;
      if (curadj[nxt] && !visited[nxt]) {
        que.emplace_back(x + dx, y + dy);
      }
    }
  }

  return area;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> N >> M;
  vector<tuple<i64, i64, i64>> verticals(N);
  vector<tuple<i64, i64, i64>> horizontals(M);
  set<i64> xs, ys;
  xs.insert(0);
  xs.insert(INF);
  xs.insert(-INF);
  ys.insert(0);
  ys.insert(INF);
  ys.insert(-INF);
  REP(i, N) {  // vertical lines
    i64 a, b, c;
    cin >> a >> b >> c;
    verticals[i] = make_tuple(a, b, c);
    ys.insert(a);
    ys.insert(b);
    xs.insert(c);
  }
  REP(i, M) {  // horizontal lines
    i64 d, e, f;
    cin >> d >> e >> f;
    horizontals[i] = make_tuple(d, e, f);
    ys.insert(d);
    xs.insert(e);
    xs.insert(f);
  }
  vector<i64> xv(xs.begin(), xs.end());
  vector<i64> yv(ys.begin(), ys.end());
  int num_nodes = xv.size() * yv.size();
  int width = yv.size();
  vector<vector<bool>> adj(num_nodes, vector<bool>(num_nodes, true));
  REP(i, N) {
    auto [a, b, c] = verticals[i];
    int xi = lower_bound(xv.begin(), xv.end(), c) - xv.begin();
    int y1 = lower_bound(yv.begin(), yv.end(), a) - yv.begin();
    int y2 = lower_bound(yv.begin(), yv.end(), b) - yv.begin();
    for (int yd = y1; yd < y2; ++yd) {
      adj[(xi - 1) * width + yd][xi * width + yd] = false;
      adj[xi * width + yd][(xi - 1) * width + yd] = false;
    }
  }
  REP(i, M) {
    auto [d, e, f] = horizontals[i];
    int yi = lower_bound(yv.begin(), yv.end(), d) - yv.begin();
    int x1 = lower_bound(xv.begin(), xv.end(), e) - xv.begin();
    int x2 = lower_bound(xv.begin(), xv.end(), f) - xv.begin();
    for (int xd = x1; xd < x2; ++xd) {
      adj[xd * width + (yi - 1)][xd * width + yi] = false;
      adj[xd * width + yi][xd * width + (yi - 1)] = false;
    }
  }
  auto result = bfs(xv, yv, adj);
  if (!result) {
    cout << "INF" << endl;
  } else {
    cout << *result << endl;
  }
}