#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d> >(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));
#define re(c, b) for(ll c=0;c<b;c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

struct Merge{
  set<vll> lr;
  ll INF = 1000000000000000009;
  vll remove(ll a, ll b){
    if(a>b) swap(a, b);
    auto itr = lr.lower_bound(vll{b+1, 0});
    if(itr==lr.begin()) return vll{a, b};
    itr--;
    ll lef = a, ri = b;
    while((*itr)[1]>=a){
      ll now_x = (*itr)[0], now_y = (*itr)[1];
      lef = min(lef, now_x), ri = max(ri, now_y);
      if(itr==lr.begin()){
        lr.erase(itr);
        break;
      }
      itr--;
      lr.erase(vll{now_x, now_y});
    }
    return vll{lef, ri};
  }
  void merge(ll a, ll b){lr.insert(remove(a, b));}

  vll get(ll a){
    auto itr = lr.lower_bound(vll{a+1, a+1});
    if(lr.size()==0||itr==lr.begin()) return vll{INF, INF};
    itr--;
    if((*itr)[1]<a) return vll{INF, INF};
    return *itr;
  }

  bool same(ll a, ll b){
    if(get(a)[0]==-1) return false;
    if(get(a)[0]==INF) return false;
    return get(a)[0]==get(b)[0];
  }
};

typedef pair<int, int> p;
typedef pair<p, p> pp;


ll MAX = 1000000;
void err(){
  std::cout << "INF" << '\n';
  exit(0);
}

int main(int argc, char const *argv[]) {
  int n, m;std::cin >> n >> m;

  vector<vector<int>> X = VV(n, 3, 0, int);
  vector<vector<int>> Y = VV(m, 3, 0, int);

  map<ll, ll> mp;

  for(int i=0;i<n;i++){
    scanf("%d %d %d", &X[i][0], &X[i][1], &X[i][2]);
    mp.emplace(X[i][0], 0);
    mp.emplace(X[i][1], 0);
    mp.emplace(X[i][2], 0);
  }
  for(int i=0;i<m;i++){
    scanf("%d %d %d", &Y[i][0], &Y[i][1], &Y[i][2]);
    mp.emplace(Y[i][0], 0);
    mp.emplace(Y[i][1], 0);
    mp.emplace(Y[i][2], 0);
  }
  mp.emplace(1000000007, 0);
  mp.emplace(-1000000007, 0);
  mp.emplace(0, 0);


  ll c = 0;
  for(auto itr = mp.begin();itr!=mp.end();itr++, c++) (*itr).second = c;

  vector<Merge> sakux(mp.size());
  vector<Merge> sakuy(mp.size());

  for(auto v:X){
    ll a = mp.at(v[0]);
    ll b = mp.at(v[1]);
    ll c = mp.at(v[2]);
    sakux[c].merge(a, b);
  }

  for(auto v:Y){
    ll a = mp.at(v[0]);
    ll b = mp.at(v[1]);
    ll c = mp.at(v[2]);
    sakuy[a].merge(b, c);
  }

  vector<vector<bool>> l(mp.size()+10, vector<bool>(mp.size()+10, 0));
  vector<vector<bool>> ar(mp.size()+10, vector<bool>(mp.size()+10, 0));

  ll L = mp.at(-1000000007);
  ll R = mp.at(1000000007);

  vll rev(mp.size());
  for(auto itr = mp.begin();itr!=mp.end();itr++){
    rev[(*itr).second] = (*itr).first;
  }
  vvl XX = VV(mp.size(), mp.size(), 0, ll);//下に伸びているか
  vvl YY = VV(mp.size(), mp.size(), 0, ll);//右に伸びているか

  for(int i=0;i<mp.size();i++){
    for(auto itr=sakux[i].lr.begin();itr!=sakux[i].lr.end();itr++){
      ll lef = (*itr)[0], ri = (*itr)[1];
      for(int j=lef;j<ri;j++) XX[i][j] = 1;
    }
    for(auto itr=sakuy[i].lr.begin();itr!=sakuy[i].lr.end();itr++){
      ll lef = (*itr)[0], ri = (*itr)[1];
      for(int j=lef;j<ri;j++) YY[i][j] = 1;
    }
  }
  ll ans = 0;
  ll z = mp.at(0);

  queue<pp> q;
  q.push(pp(p(z, z), p(MAX, MAX)));

  int dx[4] = {1, 1, -1, -1};
  int dy[4] = {-1, 1, -1, 1};

  //右上、右下、左上、左下
  while(!q.empty()){
    pp top = q.front();
    q.pop();
    int x = top.first.first, y = top.first.second;
    p pre = top.second;

    //std::cout << x << " " << y << '\n';

    //4方向
    for(int i=0;i<4;i++){
      if(pre.first!=MAX){

        if(x+dx[i]==pre.first&&y+dy[i]==pre.second) continue;

        //進行方向通りなら
        if(dx[i]==x-pre.first){
          if(YY[x][y-1]&&YY[x][y]) continue;
        }
        if(dy[i]==y-pre.second){
          if(XX[y][x-1]&&XX[y][x]) continue;
        }
        //二通りのみ
        if(dx[i]==x-pre.first&&dy[i]==y-pre.second){
          if(dx[i]*dy[i]>0){
            if(YY[x][y-1]&&XX[y][x-1]) continue;
            if(YY[x][y]&&XX[y][x]) continue;
          }else{
            if(YY[x][y-1]&&XX[y][x]) continue;
            if(YY[x][y]&&XX[y][x-1]) continue;
          }
        }
        else if(dx[i]==x-pre.first){
          if(dy[i]==1){
            if(YY[x][y]&&(XX[y][x-1]||XX[y][x])) continue;
          }else{
            if(YY[x][y-1]&&(XX[y][x-1]||XX[y][x])) continue;
          }
        }else if(dy[i]==y-pre.second){
          if(dx[i]==1){
            if(XX[y][x]&&(YY[x][y-1]||YY[x][y])) continue;
          }else{
            if(XX[y][x-1]&&(YY[x][y-1]||YY[x][y])) continue;
          }
        }
      }

      //溢れていたら終了
      if(x+dx[i]==L||x+dx[i]==R||y+dy[i]==L||y+dy[i]==R){
        err();
      }

      ll minx = min(x, x + dx[i]);
      ll miny = min(y, y + dy[i]);

      //すでに数えてたら止まる
      if(!l[minx][miny]){
        l[minx][miny] = 1;
        ll DX = abs(rev[x+dx[i]] - rev[x]);
        ll DY = abs(rev[y+dy[i]] - rev[y]);
        ans += DX*DY;
        q.push(pp(p(x+dx[i], y+dy[i]), p(x, y)));
      }

      if(!ar[x+dx[i]][y+dy[i]]){
        ar[x+dx[i]][y+dy[i]] = 1;
        q.push(pp(p(x+dx[i], y+dy[i]), p(x, y)));
      }
    }
  }
  std::cout << ans << '\n';
  return 0;
}


Measured memory_bytes: 577044