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

typedef long long ll;
#define REP(i,n) for(int i=0,_n=(int)(n);i<_n;++i)
#define ALL(v) (v).begin(),(v).end()
#define CLR(t,v) memset(t,(v),sizeof(t))
template<class T1,class T2>ostream& operator<<(ostream& os,const pair<T1,T2>&a){return os<<"("<<a.first<<","<<a.second<< ")";}
template<class T>void pv(T a,T b){for(T i=a;i!=b;++i)cout<<(*i)<<" ";cout<<endl;}
template<class T>void chmin(T&a,const T&b){if(a>b)a=b;}
template<class T>void chmax(T&a,const T&b){if(a<b)a=b;}


int nextInt() { int x; scanf("%d", &x); return x;}
ll nextLong() { ll x; scanf("%lld", &x); return x;}

// 座標圧縮
vector<ll> rev; // 圧縮後の値から元の値への写像
vector<int> normalize(const vector<ll> v) {
  const int N = v.size();
  vector<int> res(N);
  vector<pair<ll,int> > t(N);
  rev = vector<ll>(N);
  REP(i, N) t[i] = { v[i], i };
  sort(ALL(t));
  int r = 0;
  REP(i, N) {
    r += (i > 0 && t[i - 1].first != t[i].first);
    res[t[i].second] = r;
    rev[r] = t[i].first;
  }
  return res;
}

const int SZ = 2000 * 3 * 2 + 10;
bool t[SZ][SZ];
bool vis[SZ][SZ];

int main2() {
  CLR(t, 0);
  CLR(vis, 0);

  int N = nextInt();
  int M = nextInt();

  vector<ll> raw_input;
  REP(n, N) {
    raw_input.push_back(nextInt());
    raw_input.push_back(nextInt());
    raw_input.push_back(nextInt());
  }
  REP(m, M) {
    raw_input.push_back(nextInt());
    raw_input.push_back(nextInt());
    raw_input.push_back(nextInt());
  }

  raw_input.push_back(0);
  raw_input.push_back(1000000000 + 10);
  raw_input.push_back(-(1000000000 + 10));
  vector<int> input = normalize(raw_input);

  const int I = input.size();

  for (int i = 0; i < 3*N; i += 3) {
    int A = 1+2*input[i];
    int B = 1+2*input[i+1];
    int C = 1+2*input[i+2];
    for (int x = A; x <= B; x++) t[x][C] = true;
  }
  for (int i = 3*N; i < 3*N+3*M; i += 3) {
    int D = 1+2*input[i];
    int E = 1+2*input[i+1];
    int F = 1+2*input[i+2];
    for (int x = E; x <= F; x++) t[D][x] = true;
  }

  const int dr[] = {0, 1, 0, -1};
  const int dc[] = {1, 0, -1, 0};

  bool inf = false;

  // pv(ALL(input));

  queue<int> q;
  int zero = input[3*N+3*M] * 2;
  q.push(zero);
  q.push(zero);
  vis[zero][zero] = true;
  while (!q.empty()) {
    const int r = q.front(); q.pop();
    const int c = q.front(); q.pop();
    if (r <= 1 && c <= 1) {
      inf = true;
      break;
    }
    REP(i, 4) {
      const int nr = r + dr[i] * 2;
      const int nc = c + dc[i] * 2;
      if (!(0 <= nr && nr < 2*I && 0 <= nc && nc < 2*I)) continue;
      if (vis[nr][nc]) continue;
      if (t[r + dr[i]][c+dc[i]]) continue;
      vis[nr][nc] = true;
      q.push(nr);
      q.push(nc);
    }
  }

  // REP(i, I) {
  //   REP(j, I) {
  //     if (vis[i][j]) {
  //       cout << "o";
  //     } else {
  //       cout << (t[i][j] ? "#" : ".");
  //     }
  //   }
  //   cout << endl;
  // }

  if (inf) {
    cout << "INF" << endl;
  } else {
    ll ans = 0;
    REP(r, I) REP(c, I) {
      if (vis[2*r][2*c]) {
        // cout << "r=" << rev[r] << ", c=" << rev[c] << endl;
        ans += (rev[r]-rev[r-1]) * (rev[c]-rev[c-1]);
      }
    }
    cout << ans << endl;
  }
  return 0;
}

int main() {

#ifdef LOCAL
  for (;!cin.eof();cin>>ws)
#endif
    main2();
  return 0;
}

Measured memory_bytes: 285572