#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define FOR(i,n,m) for(int i=(int)(n); i<=(int)(m); i++)
#define RFOR(i,n,m) for(int i=(int)(n); i>=(int)(m); i--)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define RITR(x,c) for(__typeof(c.rbegin()) x=c.rbegin();x!=c.rend();x++)
#define setp(n) fixed << setprecision(n)

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

#define ll long long
#define vll vector<ll>
#define vi vector<int>
#define pll pair<ll,ll>
#define pi pair<int,int>

#define all(a) (a.begin()),(a.end())
#define rall(a) (a.rbegin()),(a.rend())
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert

using namespace std;

struct Segment{int a,b,c;};
using Segments = vector<Segment>;
istream &operator>>(istream &is, Segment &s){
    return is>>s.a>>s.b>>s.c;
}


tuple<int,int,int,int> compress(Segments &X, Segments &Y, vi &dX, vi &dY)
{
    vi xs,ys;
    xs.pb(0); ys.pb(0);
    for(auto e:X){
        xs.pb(e.a);
        xs.pb(e.b);
        ys.pb(e.c);
    }
    for(auto e:Y){
        xs.pb(e.a);
        ys.pb(e.b);
        ys.pb(e.c);
    }
    sort(all(xs));
    sort(all(ys));
    xs.erase(unique(all(xs)), xs.end());
    ys.erase(unique(all(ys)), ys.end());

    rep(i,xs.size()-1) dX.pb(xs[i+1]-xs[i]);
    rep(i,ys.size()-1) dY.pb(ys[i+1]-ys[i]);

    for(auto &e:X){
        e.a = find(all(xs),e.a)-xs.begin();
        e.b = find(all(xs),e.b)-xs.begin();
        e.c = find(all(ys),e.c)-ys.begin();
    }
    for(auto &e:Y){
        e.a = find(all(xs),e.a)-xs.begin();
        e.b = find(all(ys),e.b)-ys.begin();
        e.c = find(all(ys),e.c)-ys.begin();
    }
    int sx = find(all(xs),0)-xs.begin();
    int sy = find(all(ys),0)-ys.begin();
    return {xs.size(),ys.size(),sx,sy};
}

//-------------------------------------------------
//--Grid BFS
//-------------------------------------------------

template<typename T>
ll gBFS(int si, int sj, vector<T> &field)
{
    ll ret=0;
    int dx[]={0,1,0,-1};
    int dy[]={1,0,-1,0};
    int h = field.size();
    int w = field[0].size();
    using P = pair<int,int>;
    queue<P> que;
    que.emplace(si,sj);
    vector<vector<bool> > used(h,vector<bool>(w,false));
    used[si][sj] = true;
    while(que.size()){
        int x,y;
        tie(y,x) = que.front(); que.pop();
        for(int i=0; i<4; i++){
            int tx = x+dx[i];
            int ty = y+dy[i];
            if (!(0<=tx&&tx<w&&0<=ty&&ty<h)){
                return -1;
            }
            if (used[ty][tx]) continue;
            // 壁の条件(適宜書き換える)
            if (field[ty][tx]==-1) continue;
            used[ty][tx] = true;
            ret+=field[ty][tx];
            que.emplace(ty,tx);
        }
    }
    return ret;
}

//-------------------------------------------------

int main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N,M; cin>>N>>M;
    Segments X(N),Y(M);
    vi dX,dY;
    rep(i,N) cin>>X[i];
    rep(i,M) cin>>Y[i];
    auto [H,W,sx,sy] = compress(X,Y,dX,dY);
    assert(H<=3001);
    assert(W<=3001);
    vector<vll> f(2*H-1,vll(2*W-1));
    for(auto e:X){
        FOR(i,e.a*2,e.b*2){
            f[i][e.c*2] = -1;
        }
    }
    for(auto e:Y){
        FOR(j,e.b*2,e.c*2){
            f[e.a*2][j] = -1;
        }
    }
    rep(i,H-1)rep(j,W-1){
        f[i*2+1][j*2+1] = (ll)dX[i]*dY[j];
    }
    auto ans = gBFS(sx*2,sy*2,f);
    if (ans!=-1){
        cout<<ans<<endl;
    }else{
        cout<<"INF\n";
    }
    return 0;
}


Measured memory_bytes: 289596