#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <tuple>
#include <vector>

using namespace std;
typedef long long ll;

#define rep(i, n) for (ll i = 0; i < (n); i++)
#define reps(i, f, n) for (ll i = (f); i < (n); i++)
#define repr(i, n) for (ll i = n; i >= 0; i--)
#define repv(v) for (auto it = (v).begin(); it != (v).end(); it++)
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define pb push_back
#define INIT    \
    cin.tie(0); \
    ios::sync_with_stdio(false);

template <class T>
inline bool chmax(T& a, T b) {
    return a = (a < b) ? b : a;
}
template <class T>
inline bool chmin(T& a, T b) {
    return a = (a > b) ? b : a;
}

ll const INF = 1LL << 60;
ll const MOD = 1000000007;

const ll MAX_X = 5010;
const ll MAX_Y = 5010;
ll v_line[MAX_X][MAX_Y];
ll h_line[MAX_X][MAX_Y];
bool vis[MAX_X][MAX_Y];
int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};

int main() {
    INIT;

    ll N, M;
    cin >> N >> M;

    vector<ll> A(N), B(N), C(N), D(M), E(M), F(M);
    rep(i, N) { cin >> A[i] >> B[i] >> C[i]; }
    rep(i, M) { cin >> D[i] >> E[i] >> F[i]; }

    // 座標圧縮
    vector<ll> x_dict, y_dict;
    x_dict.pb(-INF);
    x_dict.pb(INF);
    x_dict.pb(0);
    y_dict.pb(-INF);
    y_dict.pb(INF);
    y_dict.pb(0);

    rep(i, N) {
        x_dict.pb(A[i]);
        x_dict.pb(B[i]);
        y_dict.pb(C[i]);
    }

    rep(i, M) {
        x_dict.pb(D[i]);
        y_dict.pb(E[i]);
        y_dict.pb(F[i]);
    }

    sort(ALL(x_dict));
    x_dict.erase(unique(ALL(x_dict)), x_dict.end());
    sort(ALL(y_dict));
    y_dict.erase(unique(ALL(y_dict)), y_dict.end());

    // repv(x_dict) { cout << *it << " "; }
    // cout << endl;
    // repv(y_dict) { cout << *it << " "; }
    // cout << endl;

    ll W = SZ(x_dict);
    ll H = SZ(y_dict);

    // imos法による線分の判定
    rep(i, N) {
        int a = lower_bound(ALL(x_dict), A[i]) - x_dict.begin();
        int b = lower_bound(ALL(x_dict), B[i]) - x_dict.begin();
        int c = lower_bound(ALL(y_dict), C[i]) - y_dict.begin();

        // cout << "(" << A[i] << " -> " << B[i] << ", " << C[i] << ") = (" << a
        //      << " -> " << b << ", " << c << ")" << endl;
        v_line[c][a]++;
        v_line[c][b]--;
    }

    // cout << "----" << endl;
    rep(i, M) {
        int d = lower_bound(ALL(x_dict), D[i]) - x_dict.begin();
        int e = lower_bound(ALL(y_dict), E[i]) - y_dict.begin();
        int f = lower_bound(ALL(y_dict), F[i]) - y_dict.begin();

        // cout << "(" << D[i] << ", " << E[i] << " -> " << F[i] << ") = (" << d
        //      << ", " << e << " -> " << f << ")" << endl;

        h_line[e][d]++;
        h_line[f][d]--;
    }

    rep(y, H) reps(x, 1, W) v_line[y][x] += v_line[y][x - 1];
    rep(x, W) reps(y, 1, H) h_line[y][x] += h_line[y - 1][x];

    // cout << "----" << endl;
    // rep(y, H) {
    //     reps(x, 1, W) { cout << (v_line[y][x] == 1 ? '#' : '.') << " "; }
    //     cout << endl;
    // }

    // cout << "----" << endl;
    // rep(y, H) {
    //     reps(x, 1, W) { cout << (h_line[y][x] == 1 ? '#' : '.') << " "; }
    //     cout << endl;
    // }

    // 座標圧縮により、x_dict, y_dictのindexを座標と再定義できる
    // - 実際の面積を求めたい場合は、idx値から各dictの要素にアクセスし、
    // - 前後の値を引くことにより面積を計算する

    ll res = 0;
    queue<pair<ll, ll>> que;

    ll stx = lower_bound(ALL(x_dict), 0) - x_dict.begin();
    ll sty = lower_bound(ALL(y_dict), 0) - y_dict.begin();

    vis[sty][stx] = true;
    que.push({stx, sty});

    while (!que.empty()) {
        ll ix, iy;
        tie(ix, iy) = que.front();
        que.pop();

        if (ix == 0 || ix == W - 1) {
            res = INF;
            break;
        }
        if (iy == 0 || iy == H - 1) {
            res = INF;
            break;
        }

        res += (x_dict[ix + 1] - x_dict[ix]) * (y_dict[iy + 1] - y_dict[iy]);

        rep(d, 4) {
            ll ix2 = ix + dx[d];
            ll iy2 = iy + dy[d];

            if (0 <= ix2 && ix2 < W && 0 <= iy2 && iy2 < H && !vis[iy2][ix2]) {
                if (ix == ix2) {
                    if (v_line[max(iy, iy2)][ix2]) continue;
                } else {
                    if (h_line[iy][max(ix, ix2)]) continue;
                }

                vis[iy2][ix2] = true;
                que.push({ix2, iy2});
            }
        }
    }

    if (res == INF)
        cout << "INF" << endl;
    else
        cout << res << endl;
    return 0;
}

Measured memory_bytes: 183264