#include <bits/stdc++.h>
using namespace std;
template <typename T>
void out(T x) {
  cout << x << endl;
  exit(0);
}
using ll = long long;
const ll inf = 1e10;
const int maxn = 1010;
int n, m;
ll A[maxn], B[maxn], C[maxn], D[maxn], E[maxn], F[maxn];
vector<ll> ordX, ordY;
int compress(ll x, const vector<ll>& ord) {
  return std::lower_bound(ord.begin(), ord.end(), x) - ord.begin();
}
int DX[4] = {1, -1, 0, 0};
int DY[4] = {0, 0, 1, -1};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    cin >> A[i] >> B[i] >> C[i];
    ordX.push_back(A[i]);
    ordX.push_back(B[i]);
    ordY.push_back(C[i]);
  }
  for (int i = 0; i < m; i++) {
    cin >> D[i] >> E[i] >> F[i];
    ordX.push_back(D[i]);
    ordY.push_back(E[i]);
    ordY.push_back(F[i]);
  }
  ordX.push_back(-inf);
  ordX.push_back(+inf);
  ordX.push_back(0);
  ordY.push_back(-inf);
  ordY.push_back(+inf);
  ordY.push_back(0);
  sort(ordX.begin(), ordX.end());
  ordX.erase(unique(ordX.begin(), ordX.end()), ordX.end());
  sort(ordY.begin(), ordY.end());
  ordY.erase(unique(ordY.begin(), ordY.end()), ordY.end());
  int N = ordX.size();
  int M = ordY.size();
  vector<vector<vector<int>>> g(N, vector<vector<int>>(M, vector<int>(4, 1)));
  vector<vector<int>> viz(N, vector<int>(M, 0));
  auto flood = [&](int x, int y, int cc) {
    queue<pair<int, int>> qq;
    qq.emplace(x, y);
    vector<pair<int, int>> pts;
    while (qq.size()) {
      auto cur = qq.front();
      qq.pop();
      int x = cur.first;
      int y = cur.second;
      if (x < 0 || y < 0 || x >= N || y >= M) continue;
      if (viz[x][y]) continue;
      pts.emplace_back(x, y);
      viz[x][y] = cc;
      for (int k = 0; k < 4; k++) {
        if (g[x][y][k]) {
          int nx = DX[k] + x;
          int ny = DY[k] + y;
          qq.emplace(nx, ny);
        }
      }
    }
    return (int)pts.size();
  };
  for (int z = 0; z < n; z++) {
    int xl = compress(A[z], ordX);
    int xr = compress(B[z], ordX);
    int y = compress(C[z], ordY);
    for (int i = xl + 1; i <= xr; i++) {
      g[i][y][2] = 0;
      g[i][y + 1][3] = 0;
    }
  }
  for (int z = 0; z < m; z++) {
    int x = compress(D[z], ordX);
    int yl = compress(E[z], ordY);
    int yr = compress(F[z], ordY);
    for (int j = yl + 1; j <= yr; j++) {
      g[x][j][0] = 0;
      g[x + 1][j][1] = 0;
    }
  }
  int cc = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      if (!viz[i][j]) {
        flood(i, j, ++cc);
      }
    }
  }
  auto print = [&]() {
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < M; j++) {
        cout << viz[i][j];
      }
      cout << endl;
    }
  };
  vector<ll> sizes(cc + 10, 0);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      sizes[viz[i][j]]++;
    }
  }
  int at = viz[compress(0, ordX)][compress(0, ordY)];
  int all = N * M;
  if (sizes[at] == all) out("INF");
  ll res = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      if (viz[i][j] == at) {
        assert(i > 0);
        assert(j > 0);
        ll dx = ordX[i] - ordX[i - 1];
        ll dy = ordY[j] - ordY[j - 1];
        ll square = dx * dy;
        res += square;
      }
    }
  }
  cout << res << endl;
  return 0;
}
