#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <chrono>

    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("unroll-loops")
    /*#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma GCC target ("avx2")*/

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;

ll MAX = 1e15;
double PI = 3.141592653589793238463;
//double PI = acos(-1);
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;


vector<vector<set<pair<ll,ll>>>> g;

void unitesame(vector<pair<ll, pair<ll,ll>>> &vert, vector<pair<ll, pair<ll,ll>>> &firstvert){
    ll a=firstvert[0].first, l=firstvert[0].second.first, r=firstvert[0].second.second;
    for(ll i=1; i<firstvert.size(); i++){
        ll a1=firstvert[i].first, l1=firstvert[i].second.first, r1=firstvert[i].second.second;
        if(a1!=a){
            vert.push_back({a, {l,r}});
            a=a1; l=l1; r=r1;
            continue;
        }
        if(l1>r){
            vert.push_back({a, {l,r}});
            a=a1; l=l1; r=r1;
            continue;
        }
        r=max(r, r1);
    }
    vert.push_back({a, {l, r}});
}

void fillbounds(vector<ll> &vertbounds, set<ll> &y){
    vertbounds[0]=-MAX;
    ll idx=1;
    for(auto x : y){
        vertbounds[idx]=x;
        idx++;
    }
    vertbounds[idx]=MAX;
}

bool checkvert(ll vert1, ll l, ll r, vector<pair<ll, pair<ll,ll>>> &vert){
    bool ans=true;
    for(ll i=0; i<vert.size(); i++){
        if(vert[i].first!=vert1){
            continue;
        }
        ll l1 =vert[i].second.first, r1 = vert[i].second.second;
        if(l1<=l && r1>=r){
            return false;
        }
    }
    return true;
}
bool checkhor(ll hor1, ll l, ll r, vector<pair<ll, pair<ll,ll>>> &hor){
    for(ll i=0; i<hor.size(); i++){
        if(hor[i].first!=hor1){
            continue;
        }
        ll l1 = hor[i].second.first, r1 = hor[i].second.second;
        if(l1<=l && r1>=r){
            return false;
        }
    }
    return true;
}

ll square(ll x1, ll x2, ll y1, ll y2){
    return abs(x2-x1)*abs(y2-y1);
}

void solve(){
    ll n,m;
    cin >> n >> m;
    set<ll> xcoords, ycoords;
    vector<pair<ll, pair<ll,ll>>> firstvert(n), firsthor(m);
    for(ll i=0; i<n; i++){
        ll a,b,c;
        cin >> a >> b >> c;
        firstvert[i] = {c, {a,b}};
        ycoords.insert(c);
    }
    for(ll i=0; i<m; i++){
        ll a,b,c;
        cin >> a >> b >> c;
        firsthor[i] = {a, {b,c}};
        xcoords.insert(a);
    }
    sort(firstvert.begin(), firstvert.end());
    sort(firsthor.begin(), firsthor.end());

    vector<pair<ll, pair<ll,ll>>> vert, hor;
    unitesame(vert, firstvert);
    unitesame(hor, firsthor);
    vector<ll> vertbounds(ycoords.size()+2), horbounds(xcoords.size()+2);
    fillbounds(vertbounds, ycoords); fillbounds(horbounds, xcoords);
    pair<ll,ll> s = {0,0};
    vector<vector<bool>> g(horbounds.size()-1, vector<bool>(vertbounds.size()-1));
    for(ll i=0; i<g.size(); i++){
        for(ll j=0; j<g[i].size(); j++){
            ll horl=horbounds[i], horr=horbounds[i+1], vertl=vertbounds[j], vertr=vertbounds[j+1];
            //cout << horl << " " << horr << " : " << vertl << " "  << vertr << "  #  ";
            if(horr>=0 && vertr>=0){
                s={i,j};
                i=g.size();
                break;
            }
        }
        //cout << "\n";
    }
    if(s.first==0 || s.first==g.size()-1 || s.second==0 || s.second==g[0].size()-1){
        cout << "INF";
        return;
    }
    //BFS
    queue<pair<ll,ll>> q;
    ll ans=0;
    //ans = abs(horbounds[s.first+1]-horbounds[s.first])*abs(vertbounds[s.second+1]-vertbounds[s.second]);
    g[s.first][s.second]=true;
    q.push(s);
    while(!q.empty()){

        pair<ll,ll> p = q.front();
        ans += square(horbounds[p.first+1], horbounds[p.first], vertbounds[p.second+1], vertbounds[p.second]);
        q.pop();
        ll horl = horbounds[p.first], horr = horbounds[p.first+1];
        ll vertl =  vertbounds[p.second], vertr = vertbounds[p.second+1];

        //LEFT
        if(!g[p.first][p.second-1] && checkvert(vertl, horl, horr, vert)){
            if(p.second-1==0){
                cout << "INF";
                return;
            }
            //ans += square(horbounds[p.first+1], horbounds[p.first], vertbounds[p.second], vertbounds[p.second-1]);
            g[p.first][p.second-1]=true;
            q.push({p.first, p.second-1});
        }
        //RIGHT
        if(!g[p.first][p.second+1] && checkvert(vertr, horl, horr, vert)){
            if(p.second==g[0].size()-1){
                cout << "INF";
                return;
            }
            //ans += square(horbounds[p.first+1], horbounds[p.first], vertbounds[p.second+2], vertbounds[p.second+1]);
            g[p.first][p.second+1]=true;
            q.push({p.first, p.second+1});
        }
        //UP
        if(!g[p.first-1][p.second] && checkhor(horl, vertl, vertr, hor)){
            if(p.first-1==0){
                cout << "INF";
                return;
            }
            g[p.first-1][p.second]=true;
            q.push({p.first-1, p.second});
        }
        //DOWN
        if(!g[p.first+1][p.second] && checkhor(horr, vertl, vertr, hor)){
            if(p.first+1==g.size()-1){
                cout << "INF";
                return;
            }
            g[p.first+1][p.second]=true;
            q.push({p.first+1, p.second});
        }

    }
    cout << ans;


}


int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif


    ll t=1;
    //cin >> t;
    while(t--){
        solve();
    }


    return 0;
}


Measured memory_bytes: 4072