#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#ifdef ENABLE_DEBUG
#define dump(a) cerr<<#a<<"="<<a<<endl
#define dumparr(a,n) cerr<<#a<<"["<<n<<"]="<<a[n]<<endl
#else
#define dump(a) 
#define dumparr(a,n) 
#endif
#define FOR(i, a, b) for(ll i = (ll)a;i < (ll)b;i++)
#define For(i, a) FOR(i, 0, a)
#define REV(i, a, b) for(ll i = (ll)b-1LL;i >= (ll)a;i--)
#define Rev(i, a) REV(i, 0, a)
#define REP(a) For(i, a)
#define SIGN(a) (a==0?0:(a>0?1:-1))

typedef long long int ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<ll, ll> pll;
typedef pair<ll,pll> ppll;
typedef vector<ll> vll;
typedef long double ld;
typedef pair<ld,ld> pdd;

const ll INF=(1LL<<60);
#if __cplusplus<201700L
ll gcd(ll a, ll b) {
  a=abs(a);
  b=abs(b);
  if(a==0)return b;
  if(b==0)return a;
  if(a < b) return gcd(b, a);
  ll r;
  while ((r=a%b)) {
    a = b;
    b = r;
  }
  return b;
}
#endif
template<class T>
bool chmax(T& a,const T& b){
  if(a<b){
    a=b;
    return true;
  }
  return false;
}
template<class T>
bool chmin(T& a,const T& b){
  if(a>b){
    a=b;
    return true;
  }
  return false;
}
template<class S,class T>
std::ostream& operator<<(std::ostream& os,pair<S,T> a){
  os << "(" << a.first << "," << a.second << ")";
  return os;
}
template<class T>
std::ostream& operator<<(std::ostream& os,vector<T> a){
  os << "[ ";
  REP(a.size()){
    os<< a[i] << " ";
  }
  os<< " ]";
  return os;
}

class UF{
  vector<long> par,rank,size_uf;
  long _chunk_size;
public:
  UF(long size):_chunk_size(size){
    for (long i = 0; i < size; i++) {
      par.push_back(i);
      rank.push_back(0);
      size_uf.push_back(1);
    }
  }
  long find(long x){
    if(par[x]==x)return x;
    return par[x]=find(par[x]);
  }
  void unite(long x,long y){
    x=find(x);
    y=find(y);
    if(x==y)return;
    --_chunk_size;
    if(rank[x]<rank[y]){
      par[x]=y;
      size_uf[y]+=size_uf[x];
    }
    else{
      par[y]=x;
      size_uf[x]+=size_uf[y];
      if(rank[x]==rank[y])rank[x]++;
    }
  }
  bool same(long x,long y){
    return find(x)==find(y);
  }
  long operator [](long x){
    return this->find(x);
  }
  long size(long x){
    x=find(x);
    return size_uf[x];
  }
  long chunk_size(){
    return this->_chunk_size;
  }
};

void solve(long long N, long long M, std::vector<long long> A, std::vector<long long> B, std::vector<long long> C, std::vector<long long> D, std::vector<long long> E, std::vector<long long> F){
  vector<ll> tate,yoko;
  tate.push_back(0);
  yoko.push_back(0);
  REP(N){
    tate.push_back(C[i]);
    yoko.push_back(A[i]);
    yoko.push_back(B[i]);
  }
  REP(M){
    tate.push_back(E[i]);
    tate.push_back(F[i]);
    yoko.push_back(D[i]);
  }
  sort(tate.begin(),tate.end());
  sort(yoko.begin(),yoko.end());
  tate.erase(unique(tate.begin(),tate.end()),tate.end());
  yoko.erase(unique(yoko.begin(),yoko.end()),yoko.end());
  auto get_tate_index=[&tate](ll y){
    return lower_bound(tate.begin(),tate.end(),y)-tate.begin();
  };
  auto get_yoko_index=[&yoko](ll x){
    return lower_bound(yoko.begin(),yoko.end(),x)-yoko.begin();
  };
  vector<vector<bool>> mp(yoko.size()*2+1,vector<bool>(tate.size()*2+1,true));
  REP(N){
    ll y=get_tate_index(C[i]);
    ll lx=get_yoko_index(A[i]),rx=get_yoko_index(B[i]);
    y=y*2+1;
    lx=lx*2+1;
    rx=rx*2+1;
    FOR(j,lx,rx+1){
      mp[j][y]=false;
    }
  }
  REP(M){
    ll x=get_yoko_index(D[i]);
    ll ly=get_tate_index(E[i]),ry=get_tate_index(F[i]);
    x=x*2+1;
    ly=ly*2+1;
    ry=ry*2+1;
    FOR(j,ly,ry+1){
      mp[x][j]=false;
    }
  }
  ll ans=0;
  ll startx=get_yoko_index(0),starty=get_tate_index(0);
  startx=startx*2+1;
  starty=starty*2+1;
  queue<pll> q;
  q.push(pll(startx,starty));
  vector<vector<bool>> used(yoko.size()*2+1,vector<bool>(tate.size()*2+1,false));
  used[startx][starty]=true;
  while(!q.empty()){
    auto [cx,cy]=q.front();q.pop();
    if(cx%2==0&&cy%2==0){
      ll lenx=yoko[(cx+1)/2]-yoko[(cx-1)/2],leny=tate[(cy+1)/2]-tate[(cy-1)/2];
      ans+=lenx*leny;
    }

    for (auto [dx,dy] : {pll(1,0),pll(0,1),pll(-1,0),pll(0,-1)})
    {
      ll x=cx+dx,y=cy+dy;
      if(0<=x&&x<mp.size()&&0<=y&&y<mp[0].size()&&mp[x][y]&&used[x][y]==false){
        if(0==x||x==mp.size()-1||y==0||y==mp[0].size()-1){
          cout<<"INF"<<endl;
          return;
        }
        used[x][y]=true;
        q.push(pll(x,y));
      }
    }
  }
  cout<<ans<<endl;
}

int main(){
  cout<<setprecision(1000);
    long long N;
    scanf("%lld",&N);
    long long M;
    scanf("%lld",&M);
    std::vector<long long> A(N);
    std::vector<long long> B(N);
    std::vector<long long> C(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&A[i]);
        scanf("%lld",&B[i]);
        scanf("%lld",&C[i]);
    }
    std::vector<long long> D(M);
    std::vector<long long> E(M);
    std::vector<long long> F(M);
    for(int i = 0 ; i < M ; i++){
        scanf("%lld",&D[i]);
        scanf("%lld",&E[i]);
        scanf("%lld",&F[i]);
    }
    solve(N, M, std::move(A), std::move(B), std::move(C), std::move(D), std::move(E), std::move(F));
    return 0;
}


Measured memory_bytes: 12840