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

#define pb push_back

#define int ll
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vpii = vector<pii>;
using vvpii = vector<vpii>;

template<typename T, typename U>
ostream& operator<<(ostream& o, const pair<T,U>& p) {
  return o << "(" << p.first << "," << p.second << ")";
}

template<typename T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  o << "[";
  for (const T& x : v)
    o << x << ",";
  return o << "]";
}

template<typename T>
ostream& operator<<(ostream& o, const vector<vector<T>>& v) {
  o << "[";
  for (const vector<T>& x : v)
    o << x << ",\n";
  return o << "]";
}

const int INF = 1.5e9;

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);

  int n, m;
  cin >> n >> m;

  vi xc;
  vi yc;
  xc.pb(0);  // start
  yc.pb(0);
  xc.pb(-INF);  // outside. means (area > 4.1e18  <->  area unbounded) b/c task coords abs <= 1e9
  xc.pb(INF);
  yc.pb(-INF);
  yc.pb(INF);

  map<int,set<pii>> ns;
  map<int,set<pii>> we;
  for (int i=0; i<n; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    if (a > b)
      swap(a, b);
    ns[c].insert({a,b});
    xc.pb(a);
    xc.pb(b);
    yc.pb(c);
  }
  for (int i=0; i<m; ++i) {
    int d, e, f;
    cin >> d >> e >> f;
    if (e > f)
      swap(e, f);
    we[d].insert({e,f});
    xc.pb(d);
    yc.pb(e);
    yc.pb(f);
  }
  set<int> xcos(xc.begin(), xc.end());
  set<int> ycos(yc.begin(), yc.end());
  vi xind2c(xcos.begin(), xcos.end());
  vi yind2c(ycos.begin(), ycos.end());

  //cerr << "DBG xind2c " << xind2c << ", yind2c " << yind2c << endl;

  map<int,int> xc2ind;
  for (int i=0; i<xind2c.size(); ++i)
    xc2ind[xind2c[i]] = i;
  map<int,int> yc2ind;
  for (int i=0; i<yind2c.size(); ++i)
    yc2ind[yind2c[i]] = i;

  const int xlen = xind2c.size();
  const int ylen = yind2c.size();
  vvi egright(xlen-1, vi(ylen-1, 1));  // right ~ inc y
  for (int x=0; x<xlen-1; ++x)
    egright[x][ylen-2] = 0;
  vvi egdown(xlen-1, vi(ylen-1, 1));  // down ~ inc x
  for (int y=0; y<ylen-1; ++y)
    egdown[xlen-2][y] = 0;
  vvi egleft(xlen-1, vi(ylen-1, 1));
  for (int x=0; x<xlen-1; ++x)
    egleft[x][0] = 0;
  vvi egup(xlen-1, vi(ylen-1, 1));
  for (int y=0; y<ylen-1; ++y)
    egup[0][y] = 0;
  for (const auto& ls : ns) {  // y=l.first, x=from l.second.first to l.second.second
    int yr = ls.first;
    for (const auto& l : ls.second) {
      int xr1, xr2;
      tie(xr1, xr2) = l;
      assert(yc2ind.count(yr));
      assert(xc2ind.count(xr1));
      assert(xc2ind.count(xr2));
      int yi = yc2ind[yr];
      int xi1 = xc2ind[xr1];
      int xi2 = xc2ind[xr2];
      // the line means we have to cut connections between (x, yi-1) and (x, yi) for all x in [xi1, xi2)
      if (yi == 0)
        assert(false);  // should be -inf, no line there
      for (int x = xi1; x < xi2; ++x) {
        egright[x][yi-1] = false;
        egleft[x][yi] = false;
      }
    }
  }
  for (const auto& ls : we) {  // x=l.first, y=from l.second.first to l.second.second
    int xr = ls.first;
    for (const auto& l : ls.second) {
      int yr1, yr2;
      tie(yr1, yr2) = l;
      assert(xc2ind.count(xr));
      assert(yc2ind.count(yr1));
      assert(yc2ind.count(yr2));
      int xi = xc2ind[xr];
      int yi1 = yc2ind[yr1];
      int yi2 = yc2ind[yr2];
      // the line means we have to cut connections between (xi-1, y) and (x, y) for all y in [yi1, yi2)
      if (xi == 0)
        assert(false);  // should be -inf, no line there
      for (int y = yi1; y < yi2; ++y) {
        egdown[xi-1][y] = false;
        egup[xi][y] = false;
      }
    }
  }

  //cerr << "DBG egright egleft egup egdown:\n" << egright << "\n" << egleft << "\n" << egup << "\n" << egdown << endl;

  // cow starts at node (0, 0), so on all four adjacent rectangles.
  // thus, floodfill from any of them. look up (0,0), take the rect after
  assert(xc2ind.count(0));
  assert(yc2ind.count(0));
  int x0 = xc2ind[0];
  int y0 = yc2ind[0];
  pii start = {x0, y0};  // the rectangle with x,y >= 0,0

  vvi reach(xlen-1, vi(ylen-1));
  queue<pii> q;
  q.push(start);
  reach[start.first][start.second] = 1;
  while (!q.empty()) {
    int xcurr, ycurr;
    tie(xcurr, ycurr) = q.front();
    q.pop();
    if (egright[xcurr][ycurr]) {  // inc y
      if (!reach[xcurr][ycurr+1]) {
        reach[xcurr][ycurr+1] = 1;
        q.push({xcurr, ycurr+1});
      }
    }
    if (egleft[xcurr][ycurr]) {  // dec y
      if (!reach[xcurr][ycurr-1]) {
        reach[xcurr][ycurr-1] = 1;
        q.push({xcurr, ycurr-1});
      }
    }
    if (egdown[xcurr][ycurr]) {  // inc x
      if (!reach[xcurr+1][ycurr]) {
        reach[xcurr+1][ycurr] = 1;
        q.push({xcurr+1, ycurr});
      }
    }
    if (egup[xcurr][ycurr]) {  // dec x
      if (!reach[xcurr-1][ycurr]) {
        reach[xcurr-1][ycurr] = 1;
        q.push({xcurr-1, ycurr});
      }
    }
  }

  //cerr << "DBG reach:\n" << reach << endl;

  // compute total area of rects marked in reach
  int total = 0;
  for (int x=0; x<xlen-1; ++x) {
    for (int y=0; y<ylen-1; ++y) {
      if (reach[x][y])
        total += (xind2c[x+1]-xind2c[x])*(yind2c[y+1]-yind2c[y]);
    }
  }
  if (total >= 4.1e18)
    cout << "INF\n";
  else
    cout << total << "\n";
}


Measured memory_bytes: 356944