#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>
#include <cstring>
#include <cassert>


using namespace std;
#define SZ(x) (int)(x.size())
#define REP(i, n) for(int i=0;i<n;++i)
#define FOR(i, a, b) for(int i=a;i<b;++i)
#define RREP(i, n) for(int i=n-1;i>=0;--i)
#define RFOR(i, a, b) for(int i=b-1;i>=a;--i)

#define all(x) begin(x),end(x)
#define dump(x) cerr<<#x<<" = "<<(x)<<endl
#define debug(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<< endl;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;
const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;

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 (b < a) {
        a = b;
        return true;
    }
    return false;
}


template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> p) {
    os << p.first << ":" << p.second;
    return os;
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "[";
    REP(i, SZ(v)) {
        if (i) os << ", ";
        os << v[i];
    }
    return os << "]";
}

// edit

void solve() {
    int N, M;
    cin >> N >> M;
    
    vector<int> A(N), B(N), C(N); // (A, C) -> (B, C)
    vector<int> D(M), E(M), F(M); // (D, E) -> (D, F)
    
    REP(i, N) cin >> A[i] >> B[i] >> C[i];
    REP(i, M) cin >> D[i] >> E[i] >> F[i];
    
    
    vector<int> xs, ys;
    xs.push_back(INF);
    xs.push_back(-INF);
    ys.push_back(INF);
    ys.push_back(-INF);
    
    REP(i, N){
        xs.push_back(A[i]);
        xs.push_back(B[i]);
        ys.push_back(C[i]);
    }
    
    REP(i, M){
        xs.push_back(D[i]);
        ys.push_back(E[i]);
        ys.push_back(F[i]);
    }
    
    sort(all(xs));
    xs.erase(unique(all(xs)), xs.end());
    
    sort(all(ys));
    ys.erase(unique(all(ys)), ys.end());
    
    int X = SZ(xs) - 1;
    int Y = SZ(ys) - 1;
    
    auto get_ix = [&](int x) -> int{
        auto pt = lower_bound(all(xs), x);
        return (int)(pt - xs.begin());
    };

    auto get_iy = [&](int y) -> int{
        auto pt = lower_bound(all(ys), y);
        return (int)(pt - ys.begin());
    };
    
    vector<vector<int>> grid(X, vector<int>(Y, 0));
    int dx[4] = {0,-1,0,1};
    int dy[4] = {-1,0,1,0};
    
    REP(i, N){
        // (A, C) -> (B, C)
        
        int y = get_iy(C[i]);
        int sx = get_ix(A[i]);
        int tx = get_ix(B[i]);
        for(int x = sx; x < tx; ++x){
            // (x, y - 1) | (x, y)
//            if(x == 4 && (y == 4 || y + 1 == 4)){
//                int tapu = 0;
//            }
            grid[x][y - 1] |= 1 << 2;
            grid[x][y] |= 1 << 0;
        }
    }
    
    REP(i, M){
        // (D, E) -> (D, F)
        
        int x = get_ix(D[i]);
        int sy = get_iy(E[i]);
        int st = get_iy(F[i]);
        
        for(int y = sy; y < st; ++y){
            // (x - 1, y) | (x, y)
//            if(y == 4 && (x == 4 || x + 1 == 4)){
//                int tapu = 0;
//            }
            
            grid[x - 1][y] |= 1 << 3;
            grid[x][y] |= 1 << 1;
        }
    }
    
    ll ans = 0;

    vector<vector<bool>> reach(X, vector<bool>(Y, false));
    {
        reach[get_ix(0)][get_iy(0)] = true;
        queue<P> que;
        que.push(P(get_ix(0),get_iy(0)));
        
        ll tmp = (xs[get_ix(0) + 1] - xs[get_ix(0)])
               * (ys[get_iy(0) + 1] - ys[get_iy(0)]);
        ans += tmp;
        
        while(!que.empty()){
            auto top = que.front();
            que.pop();
            int cx, cy;
            tie(cx, cy) = top;
            
            for(int k = 0; k < 4; ++k){
                if(grid[cx][cy] >> k & 1){
                    continue;
                }
                int nx = cx + dx[k];
                int ny = cy + dy[k];
                
                if(nx == 0 || nx + 1 == X || ny == 0 || ny + 1 == Y){
                    cout << "INF" << endl;
                    return;
                }
                
//                if(nx >= 0 && nx + 1 < X && ny >= 0 && ny + 1 < Y && !reach[nx][ny]){
                if(!reach[nx][ny]){
                    reach[nx][ny] = true;
                    que.push(P(nx, ny));
                    
                    ll tmp = (xs[nx + 1] - xs[nx]) * (ys[ny + 1] - ys[ny]);
                    ans += tmp;
                }
            }
        }
    }
    
//    for(int i = 0; i < X; ++i){
//        for(int j = 0; j < Y; ++j){
//            int tmp = grid[i][j];
////            cout << grid[i][j] << " ";
//            for(int k = 0; k < 4; ++k){
//                cout << (tmp >> k & 1);
//            }
//            cout << " ";
//        }
//        cout << endl;
//    }
    
    cout << ans << endl;
    
}


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
//    std::ifstream in("input.txt");
//    std::cin.rdbuf(in.rdbuf());

    solve();


    return 0;
}
