// skip until line 65
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <istream>
#include <iterator>
#include <sstream>
#include <list>
#include <map>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <iomanip>
using namespace std;

#define BR "\n"
#define REP(i, n) for(int (i)=0;(i)<(n);++(i))
#define ALL(cont) begin(cont),end(cont)
#define AS_MOD(a, b) ((((a) % (b) ) + (b)) % (b))
#define MO(a) AS_MOD(a,mod)
#define FEACH(it, cont) for(auto (it) = begin(cont); it!=end(cont);++it)
#define FEACHR(it, cont) for(auto (it) = rbegin(cont); it!=rend(cont);++it)
#define pb push_back
#define pob pop_back
#define fi first
#define se second
#define getll() ([](){ll s;scanf("%lld", &s);return s;})()
#define getld() ([](){ld s;scanf("%Lf", &s);return s;})()
#define prl(P) printf("%lld", P)
#define prd(P) printf("%.10Lf", P)
#define pr(P) printf(P)
#define MAX(V, T) V=max(V,T)
#define MIN(V, T) V=min(V,T)

#define DumpArray(cont, from, to) for(int __i=from;__i<to;++__i) {cout<<"(" <<__i<<": " << cont[__i]<<")";} cout<<endl;

/*
 * ***_bound(6)
 * 5 6 6 6 6 6 7 7 7
 *   ^lower    ^upper
 * void reverse(c.begin(), c.end())
 *
 * graph
 * seg tree
 * dp
 * brute force
 */
struct Comparator{
    int operator()(int l, int r) const {
        return r<l;
    }
};
struct Vec;
//set<int, Comparator> S;

// solution below
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;

#define MAX_N (1000)
ll INF=1000*1000*1000+10;
bool way[MAX_N*3+10][MAX_N*3+10][2]; // 0->v 1->h
bool visited[MAX_N*3+10][MAX_N*3+10];
vector<ll> A(MAX_N+10);
vector<ll> B(MAX_N+10);
vector<ll> C(MAX_N+10);
vector<ll> D(MAX_N+10);
vector<ll> E(MAX_N+10);
vector<ll> F(MAX_N+10);
vector<ll> xar,yar;
/*
2 2
-2 3 1
 -1 2 -2
 -5 3 -1
 -4 2 2
 */
int main() {
    cout.precision(15);
    cout << fixed;
    int N,M;
    cin>>N>>M;
    REP(i,N) {
        cin >>A[i]>>B[i]>>C[i];
    }
    REP(i,M) {
        cin >>D[i]>>E[i]>>F[i];
    }
    P sp;
    {
        map<ll,ll> Dict;
        vector<ll> CEF;
        REP(i,N)
            CEF.pb(C[i]);
        REP(i,M)
            CEF.pb(E[i]);
        REP(i,M)
            CEF.pb(F[i]);
        CEF.pb(0);
        sort(ALL(CEF));
        Dict.insert({CEF[0],0});
        xar.pb(CEF[0]);
        int c=0;
        for(int i=1;i<CEF.size();++i) {
            if (CEF[i]!=CEF[i-1]){
                c++;
                xar.pb(CEF[i]);
            }
            Dict.insert({CEF[i],c});
        }
        REP(i,N)
            C[i]=Dict[C[i]];
        REP(i,M)
            E[i]=Dict[E[i]];
        REP(i,M)
            F[i]=Dict[F[i]];
        sp.fi=Dict[0];
    }
    {
        map<ll,ll> Dict;
        vector<ll> CEF;
        REP(i,N)
            CEF.pb(A[i]);
        REP(i,N)
            CEF.pb(B[i]);
        REP(i,M)
            CEF.pb(D[i]);
        CEF.pb(0);
        sort(ALL(CEF));
        Dict.insert({CEF[0],0});
        yar.pb(CEF[0]);
        int c=0;
        for(int i=1;i<CEF.size();++i) {
            if (CEF[i]!=CEF[i-1]){
                c++;
                yar.pb(CEF[i]);
            }
            Dict.insert({CEF[i],c});
        }
        REP(i,N)
            A[i]=Dict[A[i]];
        REP(i,N)
            B[i]=Dict[B[i]];
        REP(i,M)
            D[i]=Dict[D[i]];
        sp.se=Dict[0];
    }
    //set connectivity
    /*DumpArray(xar,0,xar.size());
    DumpArray(yar,0,yar.size());
    cout<<sp.fi<<" "<<sp.se<<endl;
    DumpArray(A,0,N);
    DumpArray(B,0,N);
    DumpArray(C,0,N);
    DumpArray(D,0,M);
    DumpArray(E,0,M);
    DumpArray(F,0,M);*/
    REP(i,MAX_N*3+10)
        REP(j,MAX_N*3+10)
            REP(k,2)
                way[i][j][k]=true;
    REP(i,N) {
        for(ll j=A[i]+1;j<=B[i];++j) {
            way[C[i]][j][0]=false;
        }
    }
    REP(i,M) {
        for(ll j=E[i]+1;j<=F[i];++j) {
            way[j][D[i]][1]=false;
        }
    }
    //dfs
    // calc start pos
    REP(i,MAX_N*3+10)
        REP(j,MAX_N*3+10)
            visited[i][j]=false;
    stack<P> Q;
    Q.push(sp);
    visited[sp.fi][sp.se]=true;
    //cout<<"Hay"<<endl;
    while(!Q.empty()) {
        P cp=Q.top();Q.pop();
        vector<P> nps={};
        if (cp.fi<MAX_N*3+5 && way[cp.fi][cp.se][0])nps.pb({cp.fi+1,cp.se});
        if (cp.fi>0 && way[cp.fi-1][cp.se][0])nps.pb({cp.fi-1,cp.se});
        if (cp.se<MAX_N*3+5 && way[cp.fi][cp.se][1])nps.pb({cp.fi,cp.se+1});
        if (cp.se>0 && way[cp.fi][cp.se-1][1])nps.pb({cp.fi,cp.se-1});
        for(P p:nps) {
            if (!visited[p.fi][p.se]) {
                visited[p.fi][p.se]=true;
                Q.push(p);
            }
        }
    }

    if (visited[0][0]) {
        cout<<"INF"<<endl;
        exit(0);
    }
    ll ans=0;
    REP(i,MAX_N*3+10){
        REP(j,MAX_N*3+10) {
            if (visited[i][j]) {
                //cout<<i<<" "<<j<<endl;
                ans+=(xar[i]-xar[i-1])*(yar[j]-yar[j-1]);
            }
        }
    }
    cout<<ans<<endl;
}


Measured memory_bytes: 104136