#include <bits/stdc++.h>
using namespace std;
long long N, M, H, W, Q, K, A, B;
string S;
const long long MOD = 998244353;
const long long INF = (1LL << 62);
void input_edge(set<pair<long long, long long>> &s, long long a, long long b) {
  auto ite = s.upper_bound(pair<long long, long long>(b, INF));
  if (ite == s.begin()) {
    s.emplace(a, b);
  } else {
    --ite;
    if (ite->second < a) {
      s.emplace(a, b);
    } else {
      pair<long long, long long> p = *ite;
      s.erase(p);
      input_edge(s, min(p.first, a), max(p.second, b));
    }
  }
}
int main() {
  class union_find {
    vector<long> parent, tree_size;

   public:
    union_find(unsigned long _n) : parent(_n), tree_size(_n, 1) {
      for (unsigned long i = 0; i < _n; ++i) parent[i] = i;
    }
    long long find(long long x) {
      while (parent[x] != x) x = parent[x] = parent[parent[x]];
      return x;
    }
    void merge(long long a, long long b) {
      a = find(a);
      b = find(b);
      if (a == b) return;
      if (tree_size[a] < tree_size[b]) swap(a, b);
      tree_size[a] += tree_size[b];
      parent[b] = a;
      return;
    }
    bool same(long long a, long long b) {
      a = find(a);
      b = find(b);
      return a == b;
    }
  };
  cin >> N >> M;
  unordered_map<long long, set<pair<long long, long long>>> X, Y;
  set<long long> xp, yp;
  vector<long long> x(0), y(0);
  for (int i = 0; i < N; i++) {
    long long a, b, c;
    cin >> a >> b >> c;
    input_edge(Y[c], a, b);
  }
  for (int i = 0; i < M; i++) {
    long long d, e, f;
    cin >> d >> e >> f;
    input_edge(X[d], e, f);
  }
  long long temp_inf = long long(1e+9) + 1;
  for (int i = 0; i < 2; i++) {
    long long a, b, c;
    c = temp_inf * (i ? 1 : -1);
    a = -temp_inf;
    b = temp_inf;
    input_edge(Y[c], a, b);
  }
  for (int i = 0; i < 2; i++) {
    long long d, e, f;
    d = temp_inf * (i ? 1 : -1);
    e = -temp_inf;
    f = temp_inf;
    input_edge(X[d], e, f);
  }
  xp.insert(0);
  yp.insert(0);
  for (auto &s : X) {
    xp.insert(s.first);
    for (auto v : s.second) {
      yp.insert(v.first);
      yp.insert(v.second);
    }
  }
  for (auto &s : Y) {
    yp.insert(s.first);
    for (auto v : s.second) {
      xp.insert(v.first);
      xp.insert(v.second);
    }
  }
  for (long long v : xp) x.push_back(v);
  for (long long v : yp) y.push_back(v);
  long long xsz = x.size(), ysz = y.size();
  union_find uf((xsz + 1) * (ysz + 1));
  for (int i = 0; i < xsz - 1; i++) {
    for (int j = 0; j < ysz - 1; j++) {
      if (i > 0) {
        auto ite =
            X[x[i]].upper_bound(pair<long long, long long>(y[j + 1], INF));
        if (ite == X[x[i]].begin()) {
          uf.merge(i * ysz + j, (i - 1) * ysz + j);
        } else {
          --ite;
          if (ite->first > y[j] || y[j + 1] > ite->second) {
            uf.merge(i * ysz + j, (i - 1) * ysz + j);
          }
        }
      }
      if (j > 0) {
        auto ite =
            Y[y[j]].upper_bound(pair<long long, long long>(x[i + 1], INF));
        if (ite == Y[y[j]].begin()) {
          uf.merge(i * ysz + j, i * ysz + j - 1);
        } else {
          --ite;
          if (ite->first > x[i] || x[i + 1] > ite->second) {
            uf.merge(i * ysz + j, i * ysz + j - 1);
          }
        }
      }
    }
  }
  long long ans = 0;
  long long O_ID =
      (long long)(lower_bound(x.begin(), x.end(), 0) - x.begin()) * ysz +
      (long long)(lower_bound(y.begin(), y.end(), 0) - y.begin());
  for (int i = 0; i < xsz - 1; i++) {
    for (int j = 0; j < ysz - 1; j++) {
      if (uf.same(i * ysz + j, O_ID)) {
        ans += (x[i + 1] - x[i]) * (y[i + 1] - y[i]);
      }
    }
  }
  if (uf.same(0, O_ID)) {
    cout << "INF" << endl;
  } else {
    cout << ans << endl;
  }
}
