#include <bits/stdc++.h>
#include <iomanip>
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;

ll N,M,H,W,Q,K,A,B;
string S;
const ll MOD = 998244353;
//const ll MOD = (1e+9) + 7;
typedef pair<ll, ll> P;
const ll INF = (1LL<<62);

void input_edge(set<P> &s, ll a, ll b){
    auto ite = s.upper_bound(P(b, INF));
    if(ite == s.begin()){
        s.emplace(a, b);
    }else{
        --ite;
        if(ite->se < a){
            s.emplace(a, b);
        }else{
            P p = *ite;
            s.erase(p);
            input_edge(s, min(p.fi, a), max(p.se, b));
        }
    }
}
int main() {
    class union_find{
            vector<long> parent, tree_size;
        public:
            union_find(unsigned long _n) : parent(_n), tree_size(_n, 1){
                for(unsigned long i = 0; i < _n; ++i)parent[i] = i;
            }
            ll find(ll x){
                while(parent[x] != x)x = parent[x] = parent[parent[x]];
                return x;
            }
            void merge(ll a, ll b){
                a = find(a);
                b = find(b);
    	    if(a==b) return;
                if(tree_size[a] < tree_size[b])swap(a, b);
                tree_size[a] += tree_size[b];
                parent[b] = a;
                return;
            }
    	bool same(ll a, ll b){
    	    a = find(a);
    	    b = find(b);
    	    return a == b;
    	}
        };
    //uf.mergeのように使う
    //ufはMAX_N+1でとるか、代入時に0-indexedにする
    cin>>N>>M;
    unordered_map<ll, set<P>> X, Y;
    set<ll> xp, yp;
    vec x(0), y(0);
    rep(i,N){
        ll a, b, c;
        cin>>a>>b>>c;
        input_edge(Y[c], a, b);
    }
    rep(i,M){
        ll d, e, f;
        cin>>d>>e>>f;
        input_edge(X[d], e, f);
    }
    ll temp_inf = ll(1e+9) + 1;
    input_edge(X[-temp_inf], -temp_inf, temp_inf);
    input_edge(X[temp_inf], -temp_inf, temp_inf);
    input_edge(Y[-temp_inf], -temp_inf, temp_inf);
    input_edge(Y[temp_inf], -temp_inf, temp_inf);
    xp.insert(0);
    yp.insert(0);
    for(auto &s : X){
        xp.insert(s.fi);
        for(auto v : s.se){
            yp.insert(v.fi);
            yp.insert(v.se);
        }
    }
    for(auto &s : Y){
        yp.insert(s.fi);
        for(auto v : s.se){
            xp.insert(v.fi);
            xp.insert(v.se);
        }
    }
    for(ll v : xp) x.push_back(v);
    for(ll v : yp) y.push_back(v);
    ll xsz = x.size(), ysz = y.size();
    union_find uf((xsz + 1) * (ysz + 1));
    rep(i,xsz - 1){
        rep(j, ysz - 1){
            if(i > 0){
                auto ite = X[x[i]].upper_bound(P(y[j+1], INF));
                if(ite == X[x[i]].begin()){
                    uf.merge(i * ysz + j, (i - 1) * ysz + j);
                }else{
                    --ite;
                    if(ite->fi > y[j] || y[j+1] > ite->se){
                        uf.merge(i * ysz + j, (i - 1) * ysz + j);
                    }
                }
            }
            if(j > 0){
                auto ite = Y[y[j]].upper_bound(P(x[i+1], INF));
                if(ite == Y[y[j]].begin()){
                    uf.merge(i * ysz + j, i * ysz + j - 1);
                }else{
                    --ite;
                    if(ite->fi > x[i] || x[i+1] > ite->se){
                        uf.merge(i * ysz + j, i * ysz + j - 1);
                    }
                }
            }
        }
    }
    ll ans = 0;
    ll O_ID = (ll)(lower_bound(ALL(x), 0) - x.begin()) * ysz + (ll)(lower_bound(ALL(y), 0) - y.begin());
    rep(i, xsz - 1){
        rep(j, ysz - 1){
            if(uf.same(i * ysz + j, O_ID)){
                ans += (x[i+1] - x[i]) * (y[j+1] - y[j]);
            }
        }
    }
    if(uf.same(0, O_ID)){
        cout<<"INF"<<endl;
    }else{
        cout<<ans<<endl;
    }
}

Measured memory_bytes: 145296