#include <bits/stdc++.h>
using namespace std;
using Int = long long;
using _int = int;
using ll = long long;
using Double = long double;
const Int INF = (1LL << 60) + 1e9;
const Int mod = (1e9) + 7;
const Double EPS = 1e-8;
const Double PI = 6.0 * asin((Double)0.5);
using P = pair<Int, Int>;
template <class T>
T Max(T& a, T b) {
  return a = max(a, b);
}
template <class T>
T Min(T& a, T b) {
  return a = min(a, b);
}
template <class T1, class T2>
ostream& operator<<(ostream& o, pair<T1, T2> p) {
  return o << "(" << p.first << "," << p.second << ")";
}
template <class T1, class T2, class T3>
ostream& operator<<(ostream& o, tuple<T1, T2, T3> t) {
  return o << "(" << get<0>(t) << "," << get<1>(t) << "," << get<2>(t) << ")";
}
template <class T1, class T2>
istream& operator>>(istream& i, pair<T1, T2>& p) {
  return i >> p.first >> p.second;
}
template <class T>
ostream& operator<<(ostream& o, vector<T> a) {
  Int i = 0;
  for (T t : a) o << (i++ ? " " : "") << t;
  return o;
}
template <class T>
istream& operator>>(istream& i, vector<T>& a) {
  for (T& t : a) i >> t;
  return i;
}
template <typename T>
class Compress {
 public:
  vector<T> X;
  bool ok;
  Compress() : ok(false){};
  Int size() {
    assert(ok);
    return X.size();
  }
  void add(T a) {
    ok = false;
    X.push_back(a);
    X.push_back(a - 1);
    X.push_back(a + 1);
  }
  void add(const vector<T> a) {
    for (T x : a) add(x);
  }
  void build() {
    ok = true;
    sort(X.begin(), X.end());
    X.erase(unique(X.begin(), X.end()), X.end());
  }
  Int getL(T x) {
    assert(ok);
    return lower_bound(X.begin(), X.end(), x) - X.begin();
  }
  Int getU(T x) {
    assert(ok);
    return upper_bound(X.begin(), X.end(), x) - X.begin();
  }
};
signed main() {
  srand((unsigned)time(NULL));
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);
  Int N, M;
  cin >> N >> M;
  using PP = pair<P, P>;
  vector<PP> A;
  Compress<Int> X, Y;
  Int T = 5;
  for (Int i = 0; i < N; i++) {
    Int a, b, c;
    cin >> a >> b >> c;
    a *= T, b *= T, c *= T;
    A.push_back(PP(P(a, c), P(b, c)));
    X.add(a);
    X.add(b);
    Y.add(c);
  }
  for (Int i = 0; i < M; i++) {
    Int d, e, f;
    cin >> d >> e >> f;
    d *= T, e *= T, f *= T;
    A.push_back(PP(P(d, e), P(d, f)));
    X.add(d);
    Y.add(e);
    Y.add(f);
  }
  X.add(-INF);
  X.add(INF);
  Y.add(-INF);
  Y.add(INF);
  for (Int i = -10; i <= 10; i++) X.add(i), Y.add(i);
  X.build();
  Y.build();
  auto get = [&](Int x, Int y) { return P(X.getL(x), Y.getL(y)); };
  Int H = Y.size();
  Int W = X.size();
  vector<vector<Int> > mp1(Y.size() + 1, vector<Int>(X.size() + 1, 0));
  vector<vector<Int> > mp2(Y.size() + 1, vector<Int>(X.size() + 1, 0));
  for (auto v : A) {
    Int x, y;
    tie(x, y) = v.first;
    Int a, b;
    tie(a, b) = v.second;
    tie(x, y) = get(x, y);
    tie(a, b) = get(a, b);
    if (x != a && y == b) {
      assert(x < a);
      mp1[y][x]++;
      mp1[y][a + 1]--;
    }
    if (x == a && y != b) {
      assert(y < b);
      mp2[y][x]++;
      mp2[b + 1][x]--;
    }
  }
  for (Int i = 0; i <= H; i++)
    for (Int j = 1; j < W; j++) mp1[i][j] += mp1[i][j - 1];
  for (Int i = 0; i <= W; i++)
    for (Int j = 1; j < H; j++) mp2[j][i] += mp2[j - 1][i];
  vector<vector<Int> > mp(Y.size() + 1, vector<Int>(X.size() + 1, 0));
  for (Int i = 0; i <= H; i++)
    for (Int j = 0; j <= W; j++) {
      if (mp1[i][j] == 1) mp[i][j] |= 1;
      if (mp2[i][j] == 1) mp[i][j] |= 2;
    }
  Int ox, oy;
  tie(ox, oy) = get(0, 0);
  mp[oy][ox] = 5;
  for (Int i = 0; i < H; i++)
    ;
  mp[oy][ox] = 0;
  vector<vector<Int> > visited(Y.size(), vector<Int>(X.size(), 0));
  queue<P> Q;
  Q.push(get(0, 0));
  while (!Q.empty()) {
    Int x, y;
    tie(x, y) = Q.front();
    Q.pop();
    if (visited[y][x]) continue;
    visited[y][x] = 1;
    Int dx[] = {0, 0, 1, -1};
    Int dy[] = {1, -1, 0, 0};
    for (Int i = 0; i < 4; i++) {
      if ((mp[y][x] >> 0 & 1) && (i == 0 || i == 1)) continue;
      if ((mp[y][x] >> 1 & 1) && (i == 2 || i == 3)) continue;
      Int nx = x + dx[i];
      Int ny = y + dy[i];
      if (nx < 0 || ny < 0 || nx >= W || ny >= H) continue;
      if (i == 2 && (mp[ny][nx] >> 1 & 1)) continue;
      if (i == 0 && (mp[ny][nx] >> 0 & 1)) continue;
      if (visited[ny][nx]) continue;
      Q.push(P(nx, ny));
    }
  }
  if (visited[0][0] || visited[H - 1][0] || visited[0][W - 1] ||
      visited[H - 1][W - 1]) {
    cout << "INF" << endl;
    return 0;
  }
  for (Int i = 0; i < H; i++)
    ;
  Int ans = 0;
  for (Int i = 0; i < H; i++)
    for (Int j = 0; j < W; j++) {
      if (visited[i][j] == 0) continue;
      ans += (X.X[j + 1] - X.X[j]) * (Y.X[i + 1] - Y.X[i]);
    }
  ans /= T * T;
  cout << ans << endl;
  return 0;
}
