#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

class UnionFind {
    int n;
    vector<int> uni;
    int forest_size;
public:
    explicit UnionFind(int n) : n(n), uni(static_cast<u32>(n), -1), forest_size(n) {};

    int root(int a){
        if (uni[a] < 0) return a;
        else return (uni[a] = root(uni[a]));
    }

    bool unite(int a, int b) {
        a = root(a);
        b = root(b);
        if(a == b) return false;
        if(uni[a] > uni[b]) swap(a, b);
        uni[a] += uni[b];
        uni[b] = a;
        forest_size--;
        return true;
    }
    int size(){ return forest_size; }
    int size(int i){ return -uni[root(i)]; }
    bool same(int a, int b) { return root(a) == root(b); }
};



int main() {
    int n, m;
    cin >> n >> m;
    vector<int> zx{-INF<int>, INF<int>}, zy{-INF<int>, INF<int>};
    vector<array<int, 3>> A(n), B(m);
    for (auto &&i : A) {
        for (int j = 0; j < 3; ++j) {
            scanf("%d", &i[j]);
        }
        zy.emplace_back(i[2]);
    }
    for (auto &&i : B) {
        for (int j = 0; j < 3; ++j) {
            scanf("%d", &i[j]);
        }
        zx.emplace_back(i[0]);
    }
    sort(zy.begin(), zy.end());
    zy.erase(unique(zy.begin(), zy.end()), zy.end());
    sort(zx.begin(), zx.end());
    zx.erase(unique(zx.begin(), zx.end()), zx.end());
    auto fx = [&](int x){ return lower_bound(zx.begin(),zx.end(), x) - zx.begin(); };
    auto fy = [&](int y){ return lower_bound(zy.begin(),zy.end(), y) - zy.begin(); };
    int h = zy.size(), w = zx.size();
    UnionFind uf((h-1)*(w-1));
    vector<vector<pair<int, int>>> P(h), Q(w);
    for (int i = 0; i < n; ++i) {
        P[fy(A[i][2])].emplace_back(A[i][0], A[i][1]);
    }
    for (int i = 0; i < m; ++i) {
        Q[fx(B[i][0])].emplace_back(B[i][1], B[i][2]);
    }
    auto f = [&](int i, int j){ return i*(w-1)+j; };
    vector<int> S(w);
    for (int i = 1; i < h-1; ++i) {
        fill(S.begin(),S.end(), 0);
        for (auto &&j : P[i]) {
            S[fx(j.first)]++;
            S[fx(j.second+1)-1]--;
        }
        for (int j = 0; j < w-1; ++j) {
            if(!S[j]) uf.unite(f(i-1, j), f(i, j));
            S[j+1] += S[j];
        }
    }
    S.resize(h);
    for (int i = 1; i < w-1; ++i) {
        fill(S.begin(),S.end(), 0);
        for (auto &&j : Q[i]) {
            S[fy(j.first)]++;
            S[fy(j.second+1)-1]--;
        }
        for (int j = 0; j < h-1; ++j) {
            if(!S[j]) uf.unite(f(j, i), f(j, i-1));
            S[j+1] += S[j];
        }
    }
    int y = fy(1)-1, x = fx(1)-1, d = f(y, x);
    ll ans = 0;
    for (int i = 0; i < h-1; ++i) {
        for (int j = 0; j < w-1; ++j) {
            if(uf.same(f(i, j), d)){
                if(!i || i == h-2 || !j || j == w-2){
                    puts("INF");
                    return 0;
                }
                ans += (ll)(zy[i+1]-zy[i])*(zx[j+1]-zx[j]);
            }
        }
    }
    cout << ans << "\n";
    return 0;
}

Measured memory_bytes: 7268