bool DBG = false;
// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
//#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using ll = long long;
using ld = long double;
//using i128 = __int128_t;
//using bint = boost::multiprecision::cpp_int
//using d1024 = boost::multiprecision::number<mp::cpp_dec_float<1024>>;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define IFOR(i,a,b) for(int i=((b)-1);i>=(a);--i)
#define RPT(i,a,b) for(int i=(a);i<((a)+(b));++i)
#define IRPT(i,a,b) for(int i=((a)+(b)-1);i>=(a);--i)
#define ALL(x) x.begin(),x.end()
#define RALL(x) x.rbegin(),x.rend()
#define fs first
#define sd second
#define couts(x) cout << (x) << (" ")
#define coutn(x) cout << (x) << ("\n")
#define ncouts(x) numout(x),outst[outst_N++] = ' '
#define ncoutn(x) numout(x),outst[outst_N++] = '\n'
#define scouts(x) strout(x),outst[outst_N++] = ' '
#define scoutn(x) strout(x),outst[outst_N++] = '\n'
#define dcouts(x) if(DBG) couts(x)
#define dcoutn(x) if(DBG) coutn(x)
#define endl "\n"
#define psb push_back
#define ppb pop_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define LBIT(x,a) (((x)>>(a))&1LL)
#define IBIT(x,a) (((x)>>(a))&1)
#define BCOUNT(x) (__builtin_popcount(x))
template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T1, typename T2> std::istream &operator>>(std::istream &is, std::pair<T1,T2> &p){is >> p.first >> p.second; return is; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::deque<T> &vec){ os << "deque["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
/*
std::ostream &operator<<(std::ostream &os, const i128 nu){
  i128 co = nu;
  if(co==0){cout << '0';}
  else{
    string ous; if(co<0){cout<<'-'; co*=-1;}
    while(co){
      ous += (co%10)+'0';
      co /= 10;
    }
    reverse(ALL(ous));
    cout<<ous;
  }
  return os;
}
std::istream &operator>>(std::istream &is, i128 &nu){ string cs; cin >> cs; nu=0;int mn=1; for(auto &x:cs) { if(x!='-'){nu*=10;nu+=(x-'0');} else mn *= -1;} nu *= mn;  return is; }

*/


template<class T> using V = vector<T>;
template<class T> using V2 = V<V<T>>;
template<class T> using V3 = V<V2<T>>;
template<class T> using V4 = V<V3<T>>;


char outst[20'000'000]; int outst_N = 0;
char outst_tmp[200];
template<class NUM >
void numout(NUM n){
  if(n<0) { n*=-1; outst[outst_N++] = '-';}
  if(n==0){ outst[outst_N++] = '0'; return;}
  int cnt = 0;
  while(n>0){
    outst_tmp[cnt++] = '0' + (n % 10);
    n /= 10;
  }
  IFOR(i,0,cnt){
    outst[outst_N++] = outst_tmp[i];
  }
}
void strout(std::string s){
  for(auto x: s){
    outst[outst_N++] = x;
  }
}

constexpr ll LINF = 1LL << 60;
constexpr int IINF = 1 << 28;
constexpr ll mod =  1'000'000'007;

set<ll> xset, yset;
V<ll> widths, heights;
V2<int> visited, blockmap;
int zerox=-200, zeroy=-200; ll ansarea = 0;

void bfs(int x, int y){
  if(visited[x][y]) return;
  using P = pair<int,int>;
  queue< P > q;
  q.push(P(x,y));
  V<int> dxv = {1,-1,0,0}, dyv={0,0,1,-1};
  visited[x][y] = 1;
  while(!q.empty()){
    auto p = q.front(); //couts(p);
    q.pop();
    FOR(i,0,4){
      int dx = dxv[i], dy = dyv[i];
      if(p.fs+dx<0 || p.fs+dx>= blockmap.size() || p.sd+dy<0 || p.sd+dy>=blockmap[0].size() ) continue;
      if(visited[p.fs+dx][p.sd+dy]==0 && blockmap[p.fs+dx][p.sd+dy]==0){
        visited[p.fs+dx][p.sd+dy] = 1;
        q.push(P(p.fs+dx,p.sd+dy));
      }
    }
    if(ansarea<0) continue;
    if( (widths[p.fs]>(1LL<<40)  && heights[p.sd]>0) || (widths[p.fs]>0  && heights[p.sd]>(1LL<<40)) ) {ansarea = -1; continue;}
    ansarea += widths[p.fs]*heights[p.sd];
  }
  //coutn("");
}

void solve(){
  int n, m; cin >> n >> m;
  V2<ll> yoko(n,V<ll>(3)), tate(m,V<ll>(3)); 
  cin >> yoko >> tate;
  //xset.insert(-LINF); xset.insert(LINF); 
  //yset.insert(-LINF); yset.insert(LINF); 
  {
    FOR(i,0,n){
      xset.insert(yoko[i][0]);
      xset.insert(yoko[i][1]);
      yset.insert(yoko[i][2]);
    }
    FOR(i,0,m){
      xset.insert(tate[i][0]);
      yset.insert(tate[i][1]);
      yset.insert(tate[i][2]);
    }
  }
  widths = V<ll>( xset.size() * 2 + 2 );
  heights = V<ll>( yset.size() * 2 + 2 );
  visited = V2<int>( xset.size() * 2 + 2, V<int>(yset.size()*2+2) );
  blockmap = V2<int>( xset.size() * 2 + 2, V<int>(yset.size()*2+2) );
  {
    map<ll,int> ashuku; int cnt = 0;ll pre = -LINF;
    for(auto &x: xset){
      if(zerox<-100 && x>=0){ zerox = 2*cnt; }
      widths[2*cnt] = x - pre;
      widths[2*cnt+1] = 0;
      ashuku[x] = 2*cnt + 1;
      pre = x;
      ++cnt;
    }
    FOR(i,0,n){
      yoko[i][0] = ashuku[ yoko[i][0] ];
      yoko[i][1] = ashuku[ yoko[i][1] ];
    }
    FOR(i,0,m){
      tate[i][0] = ashuku[ tate[i][0] ];
    }
  }
  {
    map<ll,int> ashuku; int cnt = 0;ll pre = -LINF;
    for(auto &x: yset){
      if(zeroy<-100 && x>=0){ zeroy = 2*cnt; }
      heights[2*cnt] = x - pre;
      heights[2*cnt+1] = 0;
      ashuku[x] = 2*cnt + 1;
      pre = x;
      ++cnt;
    }
    FOR(i,0,n){
      yoko[i][2] = ashuku[ yoko[i][2] ];
    }
    FOR(i,0,m){
      tate[i][2] = ashuku[ tate[i][2] ];
      tate[i][1] = ashuku[ tate[i][1] ];
    }
  }
  if(zerox < 0) zerox = 0;
  if(zeroy<0) zeroy = 0;
  FOR(i,0,n){
    if(yoko[i][0]>yoko[i][1]) swap(yoko[i][0], yoko[i][1]);
    FOR(j,yoko[i][0],yoko[i][1]+1){
      blockmap[j][yoko[i][2]] = 1;
    }
  }
  FOR(i,0,m){
    if(tate[i][1]>tate[i][2]) swap(tate[i][1], tate[i][2]);
    FOR(j,tate[i][1],tate[i][2]+1){
      blockmap[tate[i][0]][j] = 1;
    }
  }
  heights[0] = LINF;
  heights.back() = LINF;
  widths[0] = LINF;
  widths.back() = LINF;
  /*
  coutn( xset );
  coutn( widths );
  coutn( yset );
  coutn( heights );
  for(auto &x:blockmap){
    for(auto y:x) {if(y==0) cout<< "_"; else cout<<"@";}
    cout << endl;
  }
  couts(zerox); coutn(zeroy);*/
  bfs(zerox,zeroy);
  if(ansarea>=0) coutn(ansarea);
  else coutn("INF");
  //couts(blockmap.size()); couts(blockmap[0].size());
}







int main(void){
  //std::cout << std::fixed << std::setprecision(20);
  cin.tie(0);
  //ios::sync_with_stdio(false);
  solve();
  //printf("%s", outst);
  return 0;
}





Measured memory_bytes: 285800