// #define _GLIBCXX_DEBUG
// #define _LIBCPP_DEBUG 0

#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#include <array>
#include <stack>
#include <tuple>
#include <string>
#include <algorithm>
#include <functional> // greater など
#include <cmath>      // abs など
#include <numeric>    // accumulate, gcd など
#include <cassert>    // assert
#include <stdexcept>
#include <bitset>
using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i < (int)(b); i++)
typedef long long ll;

unordered_map<int,int> make_unmap(vector<int> v) {
    unordered_map<int,int> m;
    rep(i, v.size()) {
        m[v[i]] = i;
    }
    return m;
}

//////////////// //////////////// //////////////// //////////////// ////////////////
//////////////// //////////////// //////////////// //////////////// ////////////////

constexpr int x_infty = 1000'000'000 + 1;

int main()
{
    // 高速な入出力
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << setprecision(15); // 浮動小数の表示の精度

    int n, m;
    cin >> n >> m;
    vector<int> x_s = {-x_infty, -1, 0, 1, x_infty}, y_s = {-x_infty, -1, 0, 1, x_infty};
    vector<int> vert_x1(n), vert_x2(n), vert_y(n);
    rep(i, n)
    {
        cin >> vert_x1[i] >> vert_x2[i] >> vert_y[i];
        x_s.push_back(vert_x1[i]);
        x_s.push_back(vert_x2[i]);
        y_s.push_back(vert_y[i]);
    }
    vector<int> hori_x(m), hori_y1(m), hori_y2(m);
    rep(k, m)
    {
        cin >> hori_x[k] >> hori_y1[k] >> hori_y2[k];
        x_s.push_back(hori_x[k]);
        y_s.push_back(hori_y1[k]);
        y_s.push_back(hori_y2[k]);
    }
    sort(x_s.begin(), x_s.end());
    sort(y_s.begin(), y_s.end());
    x_s.erase(unique(x_s.begin(), x_s.end()), x_s.end());
    y_s.erase(unique(y_s.begin(), y_s.end()), y_s.end());

    auto x_inv = make_unmap(x_s);
    auto y_inv = make_unmap(y_s);

    vector<vector<bool>> is_wall(x_s.size() - 1, vector<bool>(y_s.size() - 1, false));
    rep(i, n)
    {
        int x1_cmp = x_inv[vert_x1[i]];
        int x2_cmp = x_inv[vert_x2[i]];
        int y_cmp = y_inv[vert_y[i]];
        for (int x_cmp = x1_cmp; x_cmp < x2_cmp; x_cmp++)
        {
            is_wall[x_cmp][y_cmp] = true;
        }
    }
    rep(k, m)
    {
        int x_cmp = x_inv[hori_x[k]];
        int y1_cmp = y_inv[hori_y1[k]];
        int y2_cmp = y_inv[hori_y2[k]];
        for (int y_cmp = y1_cmp; y_cmp < y2_cmp; y_cmp++)
        {
            is_wall[x_cmp][y_cmp] = true;
        }
    }

    bool is_infty = false;
    ll ans = 0;
    vector<vector<bool>> used(x_s.size() - 1, vector<bool>(y_s.size() - 1, false));

    int x0 = x_inv[0];
    int y0 = y_inv[0];
    auto bfs = [&](int x_cmp_0, int y_cmp_0)
    {
        queue<int> x_cmps, y_cmps;
        used[x_cmp_0][y_cmp_0] = true;
        x_cmps.push(x_cmp_0);
        y_cmps.push(y_cmp_0);
        while (!x_cmps.empty()) {
            int x_cmp = x_cmps.front(); x_cmps.pop();
            int y_cmp = y_cmps.front(); y_cmps.pop();
            ans += ((ll)x_s[x_cmp + 1] - x_s[x_cmp]) * ((ll)y_s[y_cmp + 1] - y_s[y_cmp]);
            rep(i, 2)
            {
                int dx = 1 - 2 * i;
                if (is_wall[x_cmp][y_cmp - i])
                {
                    continue;
                }
                int x_cmp_new = x_cmp + dx;
                int y_cmp_new = y_cmp;
                if (used[x_cmp_new][y_cmp_new])
                {
                    continue;
                }
                used[x_cmp_new][y_cmp_new] = true;
                if (x_cmp_new == 0 || x_cmp_new + 2 == (int)x_s.size())
                {
                    is_infty = true;
                    return;
                }
                x_cmps.push(x_cmp_new);
                y_cmps.push(y_cmp_new);
            }
            rep(i, 2)
            {
                int dy = 1 - 2 * i;
                if (is_wall[x_cmp - i][y_cmp])
                {
                    continue;
                }
                int x_cmp_new = x_cmp;
                int y_cmp_new = y_cmp + dy;
                if (used[x_cmp_new][y_cmp_new])
                {
                    continue;
                }
                used[x_cmp_new][y_cmp_new] = true;
                if (y_cmp_new == 0 || y_cmp_new + 2 == (int)y_s.size())
                {
                    is_infty = true;
                    return;
                }
                x_cmps.push(x_cmp_new);
                y_cmps.push(y_cmp_new);
            }
        }
    };
    bfs(x0, y0);
    if (is_infty)
    {
        cout << "INF\n";
    }
    else
    {
        cout << ans << '\n';
    }

    return 0;
}
