#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
using ll = long long;
using ull = unsigned long long; 
using pii =  pair<int, int>;
using pll =  pair<long long, long long>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
constexpr char ln =  '\n';
constexpr long long MOD = 1000000007;
//constexpr long long MOD = 998244353;
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) { if (a < b) { a = b; return true;} return false; }
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) { if (a > b) { a = b; return true;} return false; }
inline int popcount(int x) {return __builtin_popcount(x);}
inline int popcount(long long x) {return __builtin_popcountll(x);}
void print() { cout << "\n"; }
template<class T, class... Args>
void print(const T &x, const Args &... args) {
    cout << x << " ";
    print(args...);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////


template<typename T>
struct Compress {
    vector<T> xs;

    Compress(){};
    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);}

    int build() {
        sort(begin(xs), end(xs));
        xs.erase(unique(begin(xs), end(xs)), end(xs));
        return (int)xs.size();
    }

    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];}
};

struct Line {
    int l,r,w;
    Line() {}
    Line(int l, int r, int w) : l(l), r(r), w(w) {}
};

const int dy[4] = {-1,0,1,0};
const int dx[4] = {0,-1,0,1};

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int N,M; cin >> N >> M;
    Compress<int> ComX,ComY;
    ComX.add(0); ComY.add(0);
    vector<Line> tate, yoko;
    rep(i,N) {
        int a,b,c; cin >> a >> b >> c;
        ComY.add(a);
        ComY.add(b);
        ComX.add(c);
        tate.emplace_back(a,b,c);
    }
    rep(i,M) {
        int d,e,f; cin >> d >> e >> f;
        ComY.add(d);
        ComX.add(e);
        ComX.add(f);
        yoko.emplace_back(e,f,d);
    }
    int R = ComY.build()*2;
    int C = ComX.build()*2;
    vector<vector<int>> masu(R, vector<int>(C));
    rep(i,N) {
        int a = ComY.get(tate[i].l)*2;
        int b = ComY.get(tate[i].r)*2;
        int c = ComX.get(tate[i].w)*2;
        for (int y = a; y <= b; y++) masu[y][c] = -1; 
    }
    rep(i,M) {
        int a = ComX.get(yoko[i].l)*2;
        int b = ComX.get(yoko[i].r)*2;
        int c = ComY.get(yoko[i].w)*2;
        for (int x = a; x <= b; x++) masu[c][x] = -1; 
    }
    int sy = ComY.get(0)*2;
    int sx = ComX.get(0)*2;

    queue<pii> que;
    que.emplace(sy,sx);
    masu[sy][sx] = 1;
    while (!que.empty()) {
        auto[y,x] = que.front(); que.pop();
        rep(i,4) {
            int ny = y + dy[i];
            int nx = x + dx[i];
            if (0 > ny || ny >= R || 0 > nx || nx >= C) continue;
            if (masu[ny][nx]) continue;
            masu[ny][nx] = 1;
            que.emplace(ny,nx);
        }
    }

    ll ans = 0;
    rep(i,R) rep(j,C) {
        if (masu[i][j] != 1) continue;
        if (i == 0 || i == R-1 || j == 0 || j == C-1) {
            cout << "INF" << ln;
            return 0;
        }
        if (i%2==0 or j%2==0) continue;
        ll h = ComY[(i+1)/2] - ComY[(i-1)/2];
        ll w = ComX[(j+1)/2] - ComX[(j-1)/2];
        ans += h*w;
    }

    cout << ans << ln;
}

Measured memory_bytes: 144160