// abc168_f
#include <bits/stdc++.h>
#ifdef LOCAL
#include "../cxx-prettyprint/prettyprint.hpp"
#endif
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))
#define ALL(x) x.begin(), x.end()

#define INF ((1 << 29)-1)
#define MOD (1000000007)

#define print2D(h, w, arr) REP(i, h) { REP(j, w) cout << arr[i][j] << " "; cout << endl; }
#define print_line(vec, n) {for(int i=0;i<(n-1);i++) cout << (vec)[i] << " "; cout << (vec)[(n)-1] << endl;}
template<class T> void print(const T& x){cout << x << endl;}
template<class T, class... A> void print(const T& first, const A&... rest) { cout << first << " "; print(rest...); }
struct PreMain {PreMain(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} premain;

struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
    vector<int> rank;
    vector<int> size; // size[i]: iが親なら連結成分の数

    UnionFind(int N) : par(N), rank(N), size(N) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) {par[i] = i; rank[i] = 0; size[i] = 1;}
    }

    int find(int x) { // データxが属する木の根を再帰で得る：find(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }

    void unite(int x, int y) { // xとyの木を併合
        int rx = find(x); //xの根をrx
        int ry = find(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま

        // rank[rx] >= rank[ry] となるように rx と ry を swap
        if(rank[rx] < rank[ry]) swap(rx, ry);

        // 同じ高さだったならばまとめたことによって高さ +1
        if(rank[rx] == rank[ry]) ++rank[rx];

        par[ry] = rx; // root rx に ry の木をつなぐ
        size[rx] += size[ry];
        size[ry] = 0;

    }

    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = find(x);
        int ry = find(y);
        return rx == ry;
    }

    int get_size(int x){
        int rx = find(x);
        return size[rx];
    }
};


int main() {
#ifdef LOCAL
    ifstream in("../arg.txt"); cin.rdbuf(in.rdbuf());
#endif

    int N, M;
    cin >> N >> M;
    vector<int> A(N), B(N), C(N);
    REP(i, N) cin >> A[i] >> B[i] >> C[i];
    vector<int> D(M), E(M), F(M);
    REP(i, M) cin >> D[i] >> E[i] >> F[i];

    vector<int> Xs{(int)-2e9, 0, (int)2e9};
    vector<int> Ys{(int)-2e9, 0, (int)2e9};
    REP(i, N)  {Xs.emplace_back(A[i]); Xs.emplace_back(B[i]); Ys.emplace_back(C[i]);}
    REP(i, M)  {Xs.emplace_back(D[i]); Ys.emplace_back(E[i]); Ys.emplace_back(F[i]);}

    //　重複要素を消す
    sort( ALL( Xs ) );
    Xs.erase( unique( ALL( Xs ) ), Xs.end() );
    sort( ALL( Ys ) );
    Ys.erase( unique( ALL( Ys ) ), Ys.end() );

    int H = Xs.size();
    int W = Ys.size();

    // imos
    vector<vector<int>> imos_x(H, vector<int>(W, 0));
    vector<vector<int>> imos_y(H, vector<int>(W, 0));

    // 新しい座標の取得とimos法
    REP(i, N) {
        A[i] = distance(Xs.begin(), lower_bound(ALL(Xs), A[i]));
        B[i] = distance(Xs.begin(), lower_bound(ALL(Xs), B[i]));
        C[i] = distance(Ys.begin(), lower_bound(ALL(Ys), C[i]));
        imos_x[A[i]][C[i]]++;
        imos_x[B[i]][C[i]]--;
    }

    REP(i, M) {
        D[i] = distance(Xs.begin(), lower_bound(ALL(Xs), D[i]));
        E[i] = distance(Ys.begin(), lower_bound(ALL(Ys), E[i]));
        F[i] = distance(Ys.begin(), lower_bound(ALL(Ys), F[i]));
        imos_y[D[i]][E[i]]++;
        imos_y[D[i]][F[i]]--;
    }

    UnionFind uf(H*W);
    // imos_x は縦線
    // imos_y は横線
    // imosを伸ばすのは線の方向
    // いけるかどうかの判定は線を横切る方向
    REP(i, H) REP(j, W){
        if (i > 0) imos_x[i][j] += imos_x[i-1][j];
        if (j > 0) imos_y[i][j] += imos_y[i][j-1];

        if (i > 0 && imos_y[i][j] == 0) uf.unite(i*W+j, (i-1)*W+j);
        if (j > 0 && imos_x[i][j] == 0) uf.unite(i*W+j, i*W+(j-1));
    }

//    REP(i, H){
//        print(imos_x[i]);
//    }
//    print("asdf");
//
//    REP(i, H){
//        print(imos_y[i]);
//    }

    int sx = distance(Xs.begin(), lower_bound(ALL(Xs), 0));
    int sy = distance(Ys.begin(), lower_bound(ALL(Ys), 0));

//    REP(i, H){
//        REP(j, W){
//            if(uf.same(sx*W+sy, i*W+j)){
//                cout << "." << " ";
//            } else {
//                cout << "#" << " ";
//            }
//        }
//        cout << endl;
//    }

    if(uf.same(sx*W+sy, 0)) {
        print("INF");
        return 0;
    }

    ll ans =0;
    REP(i, H-1) REP(j, W-1) {
        if(uf.same(sx*W+sy, i*W+j)) {
            ans += (ll)(Xs[i+1]-Xs[i]) * (Ys[j+1]-Ys[j]);
        }
    }
    print(ans);


    return 0;
}


Measured memory_bytes: 179744