#include <bits/stdc++.h>
using namespace std;
const int kMax = 1000;
int A[kMax];
int B[kMax];
int C[kMax];
int D[kMax];
int E[kMax];
int F[kMax];
ostream& operator<<(ostream& os, const pair<int, int>& c) {
  cout << "{" << c.first << "," << c.second << "}";
  return os;
}
class Grid {
 public:
  Grid(const set<int>& xs, const set<int>& ys) {
    xs_.push_back(*xs.begin() - 1);
    copy(xs.begin(), xs.end(), back_inserter(xs_));
    xs_.push_back(*xs.rbegin() + 1);
    for (int i = 0; i < (int)(xs_.size()); ++i) xi_[xs_[i]] = i;
    ys_.push_back(*ys.begin() - 1);
    copy(ys.begin(), ys.end(), back_inserter(ys_));
    ys_.push_back(*ys.rbegin() + 1);
    for (int i = 0; i < (int)(ys_.size()); ++i) yi_[ys_[i]] = i;
    grid_.resize(xs_.size() * 2 - 1);
    for (int i = 0; i < (int)(grid_.size()); ++i) {
      grid_[i].resize(ys_.size() * 2 - 1);
    }
  }
  void DrawLineX(int x1, int x2, int y) {
    if (x1 > x2) swap(x1, x2);
    DrawLine(xi(x1), yi(y), xi(x2), yi(y), 1, 0);
  }
  void DrawLineY(int x, int y1, int y2) {
    if (y1 > y2) swap(y1, y2);
    DrawLine(xi(x), yi(y1), xi(x), yi(y2), 0, 1);
  }
  void DrawLine(int x, int y, int mx, int my, int dx, int dy) {
    for (; x <= mx && y <= my; x += dx, y += dy) {
      grid_[x][y] = true;
    }
  }
  int xi(int x) const {
    auto it = xi_.find(x);
    assert(it != xi_.end());
    return it->second * 2;
  }
  int yi(int y) const {
    auto it = yi_.find(y);
    assert(it != yi_.end());
    return it->second * 2;
  }
  pair<int, int> CellAt(int lower_x, int lower_y) const {
    return {xi(lower_x) + 1, yi(lower_y) + 1};
  }
  void Debug() const {
    for (int i = 0; i < (int)(grid_.size()); ++i) {
      for (int j = 0; j < (int)(grid_[i].size()); ++j) {
        cout << grid_[i][j];
      }
      cout << endl;
    }
  }
  pair<pair<int, int>, bool> Move(const pair<int, int>& c, int dx,
                                  int dy) const {
    if (grid_[c.first + dx][c.second + dy]) {
      return {{0, 0}, false};
    }
    return {{c.first + dx * 2, c.second + dy * 2}, true};
  };
  long long lower_x(const pair<int, int>& c) const { return xs_[c.first / 2]; }
  long long higher_x(const pair<int, int>& c) const {
    return xs_[(c.first + 1) / 2];
  }
  long long lower_y(const pair<int, int>& c) const { return ys_[c.second / 2]; }
  long long higher_y(const pair<int, int>& c) const {
    return ys_[(c.second + 1) / 2];
  }
  void DebugCell(const pair<int, int>& c) const {
    cout << "(" << lower_x(c) << "," << lower_y(c) << ") "
         << "(" << higher_x(c) << "," << higher_y(c) << ")" << endl;
  }
  long long AreaOf(const pair<int, int>& c) const {
    return (higher_x(c) - lower_x(c)) * (higher_y(c) - lower_y(c));
  }
  bool IsEdge(const pair<int, int>& c) const {
    return c.first == 0 || (c.first + 1) == (grid_.size() - 1) ||
           c.second == 0 || (c.second + 1) == (grid_[0].size() - 1);
  };

 private:
  vector<int> xs_, ys_;
  map<int, int> xi_, yi_;
  vector<vector<bool>> grid_;
};
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
void GridTest() {
  set<int> xs;
  xs.insert(0);
  xs.insert(-1);
  xs.insert(1);
  set<int> ys;
  ys.insert(0);
  ys.insert(1);
  Grid grid(xs, ys);
  grid.DrawLineX(-1, 1, 1);
  grid.Debug();
  pair<int, int> center = grid.CellAt(0, 0);
  cout << grid.IsEdge(center) << endl;
  cout << center.first << " " << center.second << endl;
  pair<int, int> right;
  bool ok;
  tie(right, ok) = grid.Move(center, 0, 1);
  cout << "ok:" << ok << endl;
  cout << grid.IsEdge(right) << endl;
  cout << right.first << " " << right.second << endl;
  cout << "area" << endl;
  cout << grid.AreaOf(center) << endl;
  cout << grid.lower_x(center) << " " << grid.lower_y(center) << endl;
  cout << grid.higher_x(center) << " " << grid.higher_y(center) << endl;
}
int main() {
  int N, M;
  cin >> N >> M;
  for (int i = 0; i < (int)(N); ++i) cin >> A[i] >> B[i] >> C[i];
  for (int i = 0; i < (int)(M); ++i) cin >> D[i] >> E[i] >> F[i];
  set<int> xs;
  set<int> ys;
  for (int i = 0; i < (int)(N); ++i) {
    xs.insert(A[i]);
    xs.insert(B[i]);
    ys.insert(C[i]);
  }
  for (int i = 0; i < (int)(M); ++i) {
    xs.insert(D[i]);
    ys.insert(E[i]);
    ys.insert(F[i]);
  }
  xs.insert(0);
  ys.insert(0);
  Grid grid(xs, ys);
  for (int i = 0; i < (int)(N); ++i) grid.DrawLineX(A[i], B[i], C[i]);
  for (int i = 0; i < (int)(M); ++i) grid.DrawLineY(D[i], E[i], F[i]);
  pair<int, int> init = grid.CellAt(0, 0);
  queue<pair<int, int>> que;
  que.push(init);
  set<pair<int, int>> visited;
  visited.insert(init);
  long long ans = 0;
  while (!que.empty()) {
    pair<int, int> here = que.front();
    que.pop();
    if (grid.IsEdge(here)) {
      ans = -1;
      break;
    }
    ans += grid.AreaOf(here);
    for (int i = 0; i < (int)(4); ++i) {
      pair<int, int> there;
      bool ok;
      tie(there, ok) = grid.Move(here, dx[i], dy[i]);
      if (!ok) {
        continue;
      }
      if (!(visited.insert(there)).second) {
        continue;
      }
      que.push(there);
    }
  }
  if (ans == -1) {
    cout << "INF" << endl;
  } else {
    cout << ans << endl;
  }
}
