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

//////////////////////////////   Begin Macros

#define all(x) (x).begin(), (x).end()
#define in(x, a, b) (a <= x and x < b)
#define rep(i, N) for (int i = 0; i < (int)(N); i++)
#define reprev(i, N) for (int i = (int)(N)-1; i >= 0; i--)
#define rep1(i, N) for (int i = 1; i <= (int)(N); i++)
#define rep1rev(i, N) for (int i = (int)(N); i >= 0; i--)
#define forbe(i, b, e) for (int i = (b); i < (e); i++)
#define forberev(i, b, e) for (int i = (e)-1; i >= (b); i--)
#define forfl(i, f, l) for (int i = (f); i <= (l); i++)
#define forflrev(i, f, l) for (int i = (l); i >= (f); i--)
using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;

template <typename T>
bool chmax(T &m, const T q)
{
  if (m < q)
  {
    m = q;
    return true;
  }
  else
    return false;
}
template <typename T>
bool chmin(T &m, const T q)
{
  if (m > q)
  {
    m = q;
    return true;
  }
  else
    return false;
}
template <typename T1, typename T2>
pair<T1, T2> operator+(const pair<T1, T2> &l, const pair<T1, T2> &r) { return {l.first + r.first, l.second + r.second}; }
template <typename T1, typename T2>
pair<T1, T2> operator-(const pair<T1, T2> &l, const pair<T1, T2> &r) { return {l.first - r.first, l.second - r.second}; }
template <typename T>
pair<T, T> operator*(const pair<T, T> &l, const T &r) { return {l.first * r, l.second * r}; }
template <typename T>
pair<T, T> operator/(const pair<T, T> &l, const T &r) { return {l.first / r, l.second / r}; }
template <typename T>
istream &operator>>(istream &is, vector<T> &vec)
{
  for (auto &v : vec)
    is >> v;
  return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &vec)
{
  os << "[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const deque<T> &vec)
{
  os << "deq[";
  for (auto v : vec)
    os << v << ",";
  os << "]";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const set<T> &vec)
{
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &vec)
{
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const multiset<T> &vec)
{
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &vec)
{
  os << "{";
  for (auto v : vec)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &pa)
{
  os << "(" << pa.first << "," << pa.second << ")";
  return os;
}
template <typename... Ts>
istream &operator>>(istream &is, tuple<Ts...> &theTuple)
{
  apply([&is](Ts &... tupleArgs) { ((is >> tupleArgs), ...); }, theTuple);
  return is;
}
template <typename... Ts>
ostream &operator<<(ostream &os, const tuple<Ts...> &theTuple)
{
  apply([&os](const Ts &... tupleArgs) {
    os << '(';
    size_t n(0);
    ((os << tupleArgs << (++n < sizeof...(Ts) ? "," : "")), ...);
    os << ')';
  },
        theTuple);
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const map<TK, TV> &mp)
{
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}
template <typename TK, typename TV>
ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp)
{
  os << "{";
  for (auto v : mp)
    os << v.first << "=>" << v.second << ",";
  os << "}";
  return os;
}

template <typename T>
void reset(vector<T> &v, const T reset_to)
{
  for (auto &x : v)
    x = reset_to;
}
inline int popcount(const unsigned int x) { return __builtin_popcount(x); }
#define dbg(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ") " << __FILE__ << endl;

ll nC2(ll n)
{
  return n * (n - 1) / 2;
}

const int intinf = numeric_limits<int>::max();
const ll llinf = numeric_limits<ll>::max();
const pii udlr[4] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

//////////////////////////////   End Macros

void solve()
{
  int N, M;
  cin >> N >> M;
  vector<tuple<int, int, int>> ABC(N);
  vector<tuple<int, int, int>> DEF(M);
  cin >> ABC >> DEF;

  map<int, int> x_to_i, y_to_j;
  x_to_i[0];
  y_to_j[0];
  for (auto [a, b, c] : ABC)
  {
    x_to_i[a];
    x_to_i[b];
    y_to_j[c];
  }
  for (auto [d, e, f] : DEF)
  {
    x_to_i[d];
    y_to_j[e];
    y_to_j[f];
  }

  int n = x_to_i.size() - 1;
  int m = y_to_j.size() - 1;
  vector<int> i_to_x(n + 1), j_to_y(m + 1);
  {
    int i = 0, j = 0;
    for (auto [x, _] : x_to_i)
    {
      i_to_x[i] = x;
      x_to_i[x] = i;
      i++;
    }
    for (auto [y, _] : y_to_j)
    {
      j_to_y[j] = y;
      y_to_j[y] = j;
      j++;
    }
  }

  vector<vector<bool>> vline(n, vector<bool>(m + 1, false));
  vector<vector<bool>> hline(n + 1, vector<bool>(m, false));
  for (auto [a, b, c] : ABC)
  {
    int ia = x_to_i[a];
    int ib = x_to_i[b];
    int jc = y_to_j[c];
    forbe(i, ia, ib) vline[i][jc] = true;
  }
  for (auto [d, e, f] : DEF)
  {
    int id = x_to_i[d];
    int je = y_to_j[e];
    int jf = y_to_j[f];
    forbe(j, je, jf) hline[id][j] = true;
  }

  queue<pii> que;
  vector<vector<bool>> board(n, vector<bool>(m, false));
  int i0 = x_to_i[0];
  int j0 = y_to_j[0];

  rep(i, 2) rep(j, 2)
  {
    int ti = i0 - i, tj = j0 - j;
    if (!(in(ti, 0, n) and in(tj, 0, m)))
      continue;
    board[i0 - i][j0 - j] = true;
    que.push({i0 - i, j0 - j});
  }

  bool is_inf = false;
  while (!que.empty())
  {
    pii tij = que.front();
    auto [ti, tj] = tij;
    que.pop();

    rep(k, 4)
    {
      pii nij = tij + udlr[k];
      auto [ni, nj] = nij;

      if (udlr[k].second != 0)
      {
        if (vline[ni][(tj + nj + 1) / 2])
          continue;
      }
      else
      {
        if (hline[(ti + ni + 1) / 2][nj])
          continue;
      }

      if (!(in(ni, 0, n) and in(nj, 0, m)))
      {
        is_inf = true;
        break;
      }

      if (board[ni][nj])
        continue;

      board[ni][nj] = true;
      que.push({ni, nj});
    }

    if (is_inf)
      break;
  }

  if (is_inf)
  {
    cout << "INF" << endl;
    return;
  }

  ll ans = 0;
  rep(i, n) rep(j, m)
  {
    if (!board[i][j])
      continue;

    ll dx = i_to_x[i + 1] - i_to_x[i];
    ll dy = j_to_y[j + 1] - j_to_y[j];
    ans += dx * dy;
  }
  cout << ans << endl;
}

int main()
{
  cerr << "start" << endl;
  // srand(time(0));
  cout << fixed << setprecision(15);

  solve();
  return 0;
}


Measured memory_bytes: 7648