#include <vector>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;


class DisjointSet {
    public:
        DisjointSet(int n) : N(n), sz(n), pars(n, -1) {

        }

        int find(int x) {
            return pars[x] < 0 ? x : (pars[x] = find(pars[x]));
        }

        bool merge(int x, int y) {
            x = find(x), y = find(y);
            if (x == y) {
                return false;
            }
            if (pars[x] < pars[y]) {
                swap(x, y);
            }
            pars[y] += pars[x];
            pars[x] = y;
            --sz;
            return true;
        }

        int size() {
            return sz;
        }

        int count(int x) {
            return -pars[find(x)];
        }

    private:
        int N;
        int sz;
        vector<int> pars;
};

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, m;
    cin >> n >> m;
    vector<vector<int>> V(n);
    vector<vector<int>> H(m);

    const int INF = 1 << 30;
    const int NINF = -INF;
    vector<int> X;
    vector<int> Y;
    // X.push_back(0);
    // Y.push_back(0);
    X.push_back(INF);
    X.push_back(-INF);
    Y.push_back(INF);
    Y.push_back(-INF);

    for (int i = 0; i < n; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        for (auto x : {a, b, c}) {
            V[i].push_back(x);
        }
        X.push_back(a);
        X.push_back(b);
        Y.push_back(c);
    }
    for (int i = 0; i < m; ++i) {
        int d, e, f;
        cin >> d >> e >> f;
        for (auto x : {d, e, f}) {
            H[i].push_back(x);
        }
        X.push_back(d);
        Y.push_back(e);
        Y.push_back(f);
    }
    auto shrink = [&](vector<int>& A) {
        sort(A.begin(), A.end());
        A.erase(unique(A.begin(), A.end()), A.end());
    };
    shrink(X);
    shrink(Y);

    auto index = [&](vector<int>& A, int x) {
        auto it = lower_bound(A.begin(), A.end(), x);
        assert(*it == x);
        int res = it - A.begin();
        return res;
    };

    int xn = X.size();
    int yn = Y.size();
    vector<vector<int>> rows(xn, vector<int>(yn + 2, 0));
    vector<vector<int>> cols(yn, vector<int>(xn + 2, 0));

    for (int i = 0; i < H.size(); ++i) {
        int x = H[i][0], l = H[i][1], r = H[i][2];
        if (l < r) {
            swap(l, r);
        }
        x = index(X, x);
        l = index(Y, l);
        r = index(Y, r);
        rows[x][l] += 1;
        // rows[x][r + 1] -= 1;
        rows[x][r] -= 1;
    }
    
    for (int i = 0; i < V.size(); ++i) {
        int t = V[i][0], b = V[i][1], y = V[i][2];
        if (t < b) {
            swap(t, b);
        }
        t = index(X, t);
        b = index(X, b);
        y = index(Y, y);
        cols[y][b] += 1;
        // cols[y][t + 1] -= 1;
        cols[y][t] -= 1;
    }
    for (int i = 0; i < rows.size(); ++i) {
        auto& A = rows[i];
        int n = A.size();
        for (int j = 1; j < n; ++j) {
            A[j] += A[j - 1];
        }
    }
    for (int i = 0; i < cols.size(); ++i) {
        auto& A = cols[i];
        int n = A.size();
        for (int j = 1; j < n; ++j) {
            A[j] += A[j - 1];
        }    
    }

    const long long MAXAREA = 1LL << 62;
    auto calc = [&](long long l, long long r, long long b, long long t) {
        for (auto x : {l, r, b, t}) {
            if (x >= INF || x <= -INF) {
                return MAXAREA;
            }
        }

        long long res = (r - l) * (t - b);
        assert(res >= 0);
        return res;
    };

    auto ID = [&](int x, int y) {
        return x * yn + y;
    };

    int N = xn * yn;
    vector<long long> areas(N, 0);

    DisjointSet ds(N);

    int src = -1;
    for (int i = 0; i + 1< xn; ++i) {
        int b = X[i], t = X[i + 1];
        for (int j = 0; j + 1 < yn; ++j) {
            int l = Y[j], r = Y[j + 1];
            int idx = ID(i, j);

            if (l <= 0 && r >= 0 && t >= 0 && b <= 0) {
                src = idx;
                // cout << "SSS " << b << " " << t << " " << l << " " << r << endl;
            }
            areas[idx] = calc(l, r, b, t);

            {
                int x = i, y = j + 1;
                if (x >= 0 && x + 1 < xn && y >= 0 && y + 1 < yn) {
                    int nidx = ID(x, y);
                    if (cols[y][x] == 0) {
                        ds.merge(idx, nidx);
                    }
                }
            }

            {
                int x = i + 1, y = j;
                if (x >= 0 && x + 1 < xn && y >= 0 && y + 1 < yn) {
                    int nidx = ID(x, y);
                    if (rows[x][y] == 0) {
                        ds.merge(idx, nidx);
                    }
                }
            }
        }
    }

    assert(src != -1);

    long long res = 0;
    int tar = ds.find(src);
    // int cnt = 0;
    // // cout << src << " S " << tar << " " << xn << " " << yn << endl;
    // for (int i = 0; i < N; ++i) {
    //     if (ds.find(i) == tar) {
    //         ++cnt;
    //         // cout << i << ": " << areas[i] << endl;
    //     }
    // }
    for (int i = 0; i < N; ++i) {
        if (ds.find(i) == tar) {
            long long a = areas[i];
            if (a >= MAXAREA) {
                res = MAXAREA;
                break;
            }
            res += a;
        }
    }

    if (res >= MAXAREA) {
        cout << "INF\n";
    } else {
        cout << res << '\n';
    }


    return 0;
}

Measured memory_bytes: 179824