#include <bits/stdc++.h>
using namespace std;
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
const int mod = 1000000007, MAX = 2000005;
const long long INF = mod;
struct UF {
  int n;
  vector<int> par, size;
  vector<long long> S;
  void init(int n_) {
    n = n_;
    par.assign(n, -1);
    size.assign(n, 1);
    S.assign(n, 0);
    for (int i = 0; i < n; i++) {
      par[i] = i;
    }
  }
  int root(int a) {
    if (par[a] == a)
      return a;
    else
      return par[a] = root(par[a]);
  }
  void unite(int a, int b) {
    if (root(a) != root(b)) {
      size[root(a)] += size[root(b)];
      S[root(a)] += S[root(b)];
      par[root(b)] = root(a);
    }
  }
  bool check(int a, int b) { return root(a) == root(b); }
};
int main() {
  std::ifstream in("text.txt");
  std::cin.rdbuf(in.rdbuf());
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N, M;
  cin >> N >> M;
  map<long long, int> MX, MY;
  vector<long long> X1(N + M + 5), X2(N + M + 5), Y1(N + M + 5), Y2(N + M + 5);
  UF uf;
  for (int i = 0; i < N + M; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    if (i < N) {
      MX[a] = 1;
      MX[b] = 1;
      MY[c] = 1;
      X1[i] = a;
      X2[i] = b;
      Y1[i] = c;
      Y2[i] = c;
    } else {
      MY[b] = 1;
      MY[c] = 1;
      MX[a] = 1;
      X1[i] = a;
      X2[i] = a;
      Y1[i] = b;
      Y2[i] = c;
    }
  }
  MX[0] = 1;
  MY[0] = 1;
  MX[INF] = 1;
  MX[-INF] = 1;
  MY[INF] = 1;
  MY[-INF] = 1;
  X1[N + M + 1] = -INF;
  X2[N + M + 1] = INF;
  X1[N + M + 2] = -INF;
  X2[N + M + 2] = INF;
  X1[N + M + 3] = -INF;
  X2[N + M + 3] = -INF;
  X1[N + M + 4] = INF;
  X2[N + M + 4] = INF;
  Y1[N + M + 1] = -INF;
  Y2[N + M + 1] = -INF;
  Y1[N + M + 2] = INF;
  Y2[N + M + 2] = INF;
  Y1[N + M + 3] = -INF;
  Y2[N + M + 3] = INF;
  Y1[N + M + 4] = -INF;
  Y2[N + M + 4] = INF;
  int idx = 1, idy = 1;
  for (auto it = MX.begin(); it != MX.end(); it++, idx++) {
    MX[(*it).first] = idx;
  }
  for (auto it = MY.begin(); it != MY.end(); it++, idy++) {
    MY[(*it).first] = idy;
  }
  for (int i = 0; i < N + M + 5; i++) {
    X1[i] = MX[X1[i]];
    Y1[i] = MY[Y1[i]];
    X2[i] = MX[X2[i]];
    Y2[i] = MY[Y2[i]];
  }
  vector<long long> xpos(idx), ypos(idy);
  for (auto x : MX) {
    xpos[x.second - 1] = x.first;
  }
  for (auto y : MY) {
    ypos[y.second - 1] = y.first;
  }
  uf.init(idx * idy);
  for (int i = 0; i < idx - 1; i++) {
    for (int j = 0; j < idy - 1; j++) {
      uf.S[i + j * idx] = (xpos[i + 1] - xpos[i]) * (ypos[i + 1] - ypos[i]);
    }
  }
  set<pair<int, int>> out;
  for (int i = 0; i < N + M + 5; i++) {
    for (int j = Y1[i]; j < Y2[i]; j++) {
      out.insert({X1[i] - 1 + j * idx, X1[i] + j * idx});
      out.insert({X2[i] - 1 + j * idx, X2[i] + j * idx});
    }
    for (int j = X1[i]; j < X2[i]; j++) {
      out.insert({j + (Y1[i] - 1) * idx, j + Y1[i] * idx});
      out.insert({j + (Y2[i] - 1) * idx, j + Y2[i] * idx});
    }
  }
  for (int j = 0; j < idy; j++) {
    for (int i = 0; i + 1 < idx; i++) {
      if (out.count({i + j * idx, i + 1 + j * idx}) == 0) {
        uf.unite(i + j * idx, i + 1 + j * idx);
      }
    }
  }
  for (int i = 0; i < idx; i++) {
    for (int j = 0; j + 1 < idy; j++) {
      if (out.count({i + j * idx, i + (j + 1) * idx}) == 0) {
        uf.unite(i + j * idx, i + (j + 1) * idx);
      }
    }
  }
  if (abs(uf.S[uf.root(X1[N + M] + Y1[N + M] * idx)]) >= 2000000000100000000)
    cout << "INF\n";
  else
    cout << uf.S[uf.root(X1[N + M] + Y1[N + M] * idx)] << endl;
}
