#include <bits/stdc++.h>
using namespace std;

using ll = long long;
vector<int> dx = {1, 0, -1, 0}, dy = {0, 1, 0, -1};

// 座標圧縮
map<ll, int> compress(vector<ll> &x, bool sorted = false) {
  map<ll, int> comp;
  if (!sorted) sort(x.begin(), x.end());
  x.erase(unique(x.begin(), x.end()), x.end());
  for (int i = 0; i < x.size(); i++) comp[x.at(i)] = i;
  return comp;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  
  int n, m;
  cin >> n >> m;
  
  vector<ll> x, y; // 座標圧縮用
  x.emplace_back(0);
  x.emplace_back(-1e9);
  x.emplace_back(1e9);
  y.emplace_back(0);
  y.emplace_back(-1e9);
  y.emplace_back(1e9);
  
  vector<vector<ll>> hor(n, vector<ll>(3)), ver(m, vector<ll>(3));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < 3; j++) {
      cin >> hor.at(i).at(j);
    }
    x.emplace_back(hor.at(i).at(0));
    x.emplace_back(hor.at(i).at(1));
    y.emplace_back(hor.at(i).at(2));
  }
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < 3; j++) {
      cin >> ver.at(i).at(j);
    }
    x.emplace_back(ver.at(i).at(0));
    y.emplace_back(ver.at(i).at(1));
    y.emplace_back(ver.at(i).at(2));
  }
  
  map<ll, int> mpx = compress(x), mpy = compress(y);
  vector<vector<int>> grid(mpx.size() * 2, vector<int>(mpy.size() * 2, 0)); // -1:壁, 0:未訪問, 1:訪問
  for (int i = 0; i < n; i++) {
    int xleft = mpx[hor.at(i).at(0)] * 2, xright = mpx[hor.at(i).at(1)] * 2, yy = mpy[hor.at(i).at(2)] * 2;
    for (int xx = xleft; xx <= xright; xx++) {
      grid[xx][yy] = -1;
    }
  }
  for (int i = 0; i < m; i++) {
    int xx = mpx[ver.at(i).at(0)] * 2, ybottom = mpy[ver.at(i).at(1)] * 2, ytop = mpy[ver.at(i).at(2)] * 2;
    for (int yy = ybottom; yy <= ytop; yy++) {
      grid[xx][yy] = -1;
    }
  }
  
  queue<pair<int, int>> q;
  grid[mpx[0] * 2][mpy[0] * 2] = 1;
  q.push(make_pair(mpx[0] * 2, mpy[0] * 2));
  while (!q.empty()) {
    pair<int, int> p = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      int nx = p.first + dx[i], ny = p.second + dy[i];
      if (0 <= nx && nx < grid.size() && 0 <= ny && ny < grid[0].size() && grid[nx][ny] == 0) {
        grid[nx][ny] = 1;
        q.push(make_pair(nx, ny));
        if (nx == 0 || nx == grid.size() - 1 || ny == 0 || ny == grid[0].size() - 1) {
          cout << "INF\n";
          return 0;
        }
      }
    }
  }
  
  // 圧縮座標->元の座標 へのmap
  map<int, ll> mpx2, mpy2;
  for (auto i : mpx) mpx2[i.second] = i.first;
  for (auto i : mpy) mpy2[i.second] = i.first;
  
  ll ans = 0;
  for (int i = 0; i < grid.size(); i++) {
    ll xwid = 0;
    if (i % 2 == 1) xwid = mpx2[(i + 1) / 2] - mpx2[i / 2];
    for (int j = 0; j < grid[0].size(); j++) {
      if (grid[i][j] == 1) {
        ll ywid = 0;
        if (j % 2 == 1) ywid = mpy2[(j + 1) / 2] - mpy2[j / 2];
        ans += xwid * ywid;
      }
    }
  }
  
  cout << ans << '\n';
}