#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using pii = pair<int, int>;
using pll = pair<lint, lint>;
template <typename T>
using vc = vector<T>;
template <typename T>
using vvc = vector<vector<T>>;
template <typename T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
constexpr lint ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
class FSingleDot {
 public:
  int N, M, H, W;
  vc<int> xs = {0}, ys = {0}, dx = {1, 0, -1, 0}, dy = {0, 1, 0, -1};
  vc<pair<pii, int>> xsegs;
  vc<pair<int, pii>> ysegs;
  vvc<bool> used, grid;
  inline bool valid(int x, int y) {
    return 0 <= x and x < H and 0 <= y and y < W;
  }
  inline void bfs() {
    queue<pii> que;
    int sx = 2 * (lower_bound((xs).begin(), (xs).end(), 0) - xs.begin());
    int sy = 2 * (lower_bound((ys).begin(), (ys).end(), 0) - ys.begin());
    used[sx][sy] = true;
    que.emplace(sx, sy);
    while (not que.empty()) {
      int cx = que.front().first, cy = que.front().second;
      que.pop();
      for (int i = (0); i < (4); ++i) {
        int nx = cx + dx[i], ny = cy + dy[i];
        if (not valid(nx, ny) or not grid[nx][ny] or used[nx][ny]) continue;
        used[nx][ny] = true;
        que.emplace(nx, ny);
      }
    }
  }
  void solve(std::istream& in, std::ostream& out) {
    ios_base::sync_with_stdio(false);
    in.tie(nullptr), out.tie(nullptr);
    in >> N >> M;
    xsegs.resize(N);
    ysegs.resize(M);
    for (int i = (0); i < (N); ++i) {
      in >> xsegs[i].first.first >> xsegs[i].first.second >> xsegs[i].second;
      int &a = xsegs[i].first.first, b = xsegs[i].first.second,
          c = xsegs[i].second;
      xs.push_back(a);
      xs.push_back(b);
      ys.push_back(c);
    }
    for (int i = (0); i < (M); ++i) {
      in >> ysegs[i].first >> ysegs[i].second.first >> ysegs[i].second.second;
      int &d = ysegs[i].first, e = ysegs[i].second.first,
          f = ysegs[i].second.second;
      xs.push_back(d);
      ys.push_back(e);
      ys.push_back(f);
    }
    sort((xs).begin(), (xs).end());
    sort((ys).begin(), (ys).end());
    xs.erase(unique((xs).begin(), (xs).end()), xs.end());
    ys.erase(unique((ys).begin(), (ys).end()), ys.end());
    H = 2 * (int)(xs).size();
    W = 2 * (int)(ys).size();
    grid.resize(H, vc<bool>(W, true));
    used.resize(H, vc<bool>(W, false));
    for (int i = (0); i < (N); ++i) {
      int &a = xsegs[i].first.first, b = xsegs[i].first.second,
          c = xsegs[i].second;
      int up = 2 * (lower_bound((xs).begin(), (xs).end(), a) - xs.begin());
      int bottom =
          2 * (lower_bound((xs).begin(), (xs).end(), b) - xs.begin()) + 1;
      int y = 2 * (lower_bound((ys).begin(), (ys).end(), c) - ys.begin());
      for (int j = (up); j < (bottom); ++j) grid[j][y] = false;
    }
    for (int i = (0); i < (M); ++i) {
      int &d = ysegs[i].first, e = ysegs[i].second.first,
          f = ysegs[i].second.second;
      int x = 2 * (lower_bound((xs).begin(), (xs).end(), d) - xs.begin());
      int left = 2 * (lower_bound((ys).begin(), (ys).end(), e) - ys.begin());
      int right =
          2 * (lower_bound((ys).begin(), (ys).end(), f) - ys.begin()) + 1;
      for (int j = (left); j < (right); ++j) grid[x][j] = false;
    }
    bfs();
    lint ans = 0;
    for (int i = (0); i < (H); ++i)
      for (int j = (0); j < (W); ++j) {
        if (not used[i][j] or i % 2 == 0 or j % 2 == 0) continue;
        if (i == 0 or i == H - 1 or j == 0 or j == W - 1) {
          out << "INF\n";
          return;
        }
        ans += 1ll * (xs[i / 2 + 1] - xs[i / 2]) * (ys[j / 2 + 1] - ys[j / 2]);
      }
    out << ans << '\n';
  }
};
int main() {
  FSingleDot solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  solver.solve(in, out);
  return 0;
}
