#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using vl = vector<ll>;
template<class T> using vc = vector<T>;
template<class T> using vvc = vector<vector<T>>;

#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define repr(i, n) for (ll i = (n)-1; i >= 0; i--)
#define repe(i, l, r) for (ll i = (l); i < (r); i++)
#define reper(i, l, r) for (ll i = (r)-1; i >= (l); i--)
#define repa(i,n) for (auto& i: n)

template<class T> inline bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> inline bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
void init() {cin.tie(0);ios::sync_with_stdio(false);cout << fixed << setprecision(15);}

#ifdef DEBUG
template <class T, class N> void verr(const T& a, const N& n) { rep(i, n) cerr << a[i] << " "; cerr << "\n" << flush; }
ll dbgt = 1; void err() { cerr << "passed " << dbgt++ << "\n" << flush; }
template<class H, class... T> void err(H&& h,T&&... t){ cerr<< h << (sizeof...(t)?" ":"\n") << flush; if(sizeof...(t)>0) err(forward<T>(t)...); }
#endif

const ll INF = 5e18;
const ld EPS = 1e-11;
const ld PI = acos(-1.0L);
const ll MOD = 1e9 + 7;
// const ll MOD = 998244353;
//--------------------------------------------------------------------------------//
template <typename T>
struct Compress {
    vector<T> xs;

    Compress() = default;

    Compress(const vector<T> &vs) {
        add(vs);
    }

    Compress(const initializer_list<vector<T>> &vs) {
        for (auto &p : vs) add(p);
    }

    void add(const vector<T> &vs) {
        copy(begin(vs), end(vs), back_inserter(xs));
    }

    void add(const T &x) {
        xs.emplace_back(x);
    }

    void build() {
        sort(begin(xs), end(xs));
        xs.erase(unique(begin(xs), end(xs)), end(xs));
    }

    vector<int> get(const vector<T> &vs) const {
        vector<int> ret;
        transform(begin(vs), end(vs), back_inserter(ret), [&](const T &x) {
            return lower_bound(begin(xs), end(xs), x) - begin(xs);
        });
        return ret;
    }

    int get(const T &x) const {
        return lower_bound(begin(xs), end(xs), x) - begin(xs);
    }

    const T &operator[](int k) const {
        return xs[k];
    }
};

ll G[3010][3010], Xw[3010][3010], Yw[3010][3010];
bool used[3010][3010];

ll A[1000], B[1000], C[1000], D[1000], E[1000], F[1000];

int main() {
    init();
    ll N,M;
    ll inf = (ll)(1e9 + 1);
    Compress<ll> cx({-inf, 0, inf}), cy({-inf, 0, inf});

    cin >> N >> M;

    rep(i,N){
        ll a, b, c;
        cin >> a >> b >> c;
        A[i] = a, B[i] = b, C[i] = c;
        cx.add(a), cx.add(b), cy.add(c);
    }
    rep(i,M){
        ll d, e, f;
        cin >> d >> e >> f;
        D[i] = d, E[i] = e, F[i] = f;
        cx.add(d), cy.add(e), cy.add(f);
    }

    // 座圧
    cx.build(), cy.build();
    ll xn = cx.xs.size(), yn = cy.xs.size();

    // 左下の点が右上の点までの領域を持つ
    
    // 壁判定を座標に持たせる
    rep(i,N){
        ll a = cx.get(A[i]), b = cx.get(B[i]), c = cy.get(C[i]);
        Xw[c][a + 1]++, Xw[c][b + 1]--; 
    }
    rep(i, yn) repe(j, 1, xn) Xw[i][j] += Xw[i][j - 1];

    rep(i,M){
        ll d = cx.get(D[i]), e = cy.get(E[i]), f = cy.get(F[i]);
        Yw[d][e]++, Yw[d][f]--; 
    }
    rep(i, xn) repe(j, 1, yn) Yw[i][j] += Yw[i][j - 1];

    
    ll ans = 0;
    queue<pair<ll,ll>> q;
    q.emplace(cx.get(0), cy.get(0));
    used[cx.get(0)][cy.get(0)] = true;
    vl d = {1, -1};


    while(!q.empty()){
        ll xi, yi;
        tie(xi, yi) = q.front(), q.pop();
        
        if(xi == 0 or xi == xn - 1 or yi == 0 or yi ==yn - 1){
            cout << "INF" << endl;
            return 0;
        }

        ans += (cx.xs[xi + 1] - cx.xs[xi]) * (cy.xs[yi + 1] - cy.xs[yi]);

        err(xi, yi, ans);

        // 壁が無ければinq
        rep(di, 2){
            ll tyi = yi + d[di];
            if (used[xi][tyi] or Xw[max(yi, tyi)][xi]) continue;
            q.emplace(xi, tyi);
            used[xi][tyi] = true;
        }
        rep(di, 2){
            ll txi = xi + d[di];
            if (used[txi][yi] or Yw[min(xi, txi)][yi]) continue;
            q.emplace(txi, yi);
            used[txi][yi] = true;
        }
    }

    cout << ans << endl;
}