#include <bits/stdc++.h>
using namespace std;
struct Segment {
  int a, b, c;
  Segment(int a, int b, int c) : a(a), b(b), c(c) {}
  bool operator<(const Segment that) const {
    return c < that.c ||
           (c == that.c && make_pair(a, b) < make_pair(that.a, that.b));
  }
};
const long long INF = 1e9 + 123;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<Segment> ns;
  set<int> xs, ys;
  for (int i = 0; i < n; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    ns.emplace_back(a, b, c);
    xs.insert(a);
    xs.insert(b);
    ys.insert(c);
  }
  xs.insert(-INF);
  xs.insert(INF);
  ns.emplace_back(-INF, INF, -INF);
  ns.emplace_back(-INF, INF, INF);
  n += 2;
  vector<Segment> ew;
  for (int i = 0; i < m; i++) {
    int d, e, f;
    cin >> d >> e >> f;
    ew.emplace_back(e, f, d);
    ys.insert(e);
    ys.insert(f);
    xs.insert(d);
  }
  ys.insert(-INF);
  ys.insert(INF);
  ew.emplace_back(-INF, INF, -INF);
  ew.emplace_back(-INF, INF, INF);
  m += 2;
  sort(ns.begin(), ns.end());
  sort(ew.begin(), ew.end());
  vector<int> xss(xs.begin(), xs.end());
  vector<int> yss(ys.begin(), ys.end());
  int szx = xss.size(), szy = yss.size();
  int total = (szx - 1) * (szy - 1);
  vector<int> area(total);
  vector<set<int>> no_adj(total);
  int cow = -1;
  for (int i = 0; i < xss.size() - 2; i++) {
    int x1 = xss[i], x2 = xss[i + 1];
    vector<pair<int, int>> delta;
    for (int k = 0; k < m; k++) {
      if (ew[k].c == x2) {
        delta.emplace_back(ew[k].a, 1);
        delta.emplace_back(ew[k].b, -1);
      }
    }
    sort(delta.begin(), delta.end());
    int covering = 0;
    int k = 0;
    for (int j = 0; j < yss.size() - 1; j++) {
      int y1 = yss[j], y2 = yss[j + 1];
      int number = i * szy + j;
      if (abs(x1) == INF || abs(x2) == INF || abs(y1) == INF ||
          abs(y2) == INF) {
        area[number] = INF;
      } else {
        area[number] = (y2 - y1) * (x2 - x1);
      }
      while (k < delta.size() && delta[k].first <= y1) {
        covering += delta[k].second;
        k++;
      }
      if (covering > 0) {
        int below = (i + 1) * szy + j;
        no_adj[number].insert(below);
        no_adj[below].insert(number);
      }
      if (x1 <= 0 && 0 <= x2 && y1 <= 0 && 0 <= y2) {
        cow = number;
      }
    }
  }
  for (int j = 0; j < yss.size() - 2; j++) {
    int y1 = yss[j], y2 = yss[j + 1];
    vector<pair<int, int>> delta;
    for (int k = 0; k < n; k++) {
      if (ns[k].c == y2) {
        delta.emplace_back(ns[k].a, 1);
        delta.emplace_back(ns[k].b, -1);
      }
    }
    sort(delta.begin(), delta.end());
    int covering = 0;
    int k = 0;
    for (int i = 0; i < xss.size() - 1; i++) {
      int x1 = xss[i], x2 = xss[i + 1];
      while (k < delta.size() && delta[k].first <= x1) {
        covering += delta[k].second;
        k++;
      }
      if (covering > 0) {
        int number = i * szy + j;
        int right = i * szy + j + 1;
        no_adj[number].insert(right);
        no_adj[right].insert(number);
      }
    }
  }
  queue<int> q;
  q.push(cow);
  int ans = 0;
  vector<bool> visited(total);
  visited[cow] = true;
  auto is_boarder = [&](int xy) {
    int x = xy / szy;
    int y = xy % szy;
    return x == 0 || x == szx - 1 || y == 0 || y == szy - 1;
  };
  while (!q.empty()) {
    int h = q.front();
    q.pop();
    ans += area[h];
    if (is_boarder(h)) {
      ans = INF;
      break;
    }
    const vector<int> DIR{szy, 1, -szy, -1};
    for (auto &x : DIR) {
      int next = h + x;
      if (0 <= next && next < total && !visited[next] &&
          no_adj[h].count(next) == 0) {
        visited[next] = true;
        q.push(next);
      }
    }
  }
  if (ans == INF) {
    cout << "INF" << '\n';
  } else {
    cout << ans << '\n';
  }
}
