#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using P = pair<int, int>;

constexpr char newl = '\n';
constexpr int dx[] = {1, -1, 0, 0};
constexpr int dy[] = {0, 0, 1, -1};
constexpr ll INF = 11451419190;

//引数unzipには圧縮前のvectorを入れる
int compress(vector<ll>& unzip, map<ll, int>& zip) {
    sort(unzip.begin(), unzip.end());
    unzip.erase(unique(unzip.begin(), unzip.end()), unzip.end());
    for (int i = 0; i < unzip.size(); i++) {
        zip[unzip[i]] = i;
    }
    return unzip.size();
}

struct UnionFind {
    //各要素が属する集合の代表(根)を管理する
    //もし、要素xが根であればdata[x]は負の値を取り、-data[x]はxが属する集合の大きさに等しい
    vector<int> data;

    UnionFind(int sz) : data(sz, -1) {}

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        bool is_union = (x != y);
        if (is_union) {
            if (data[x] > data[y]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        return is_union;
    }

    int find(int x) {
        if (data[x] < 0) { //要素xが根である
            return x;
        } else {
            data[x] = find(data[x]); //data[x]がxの属する集合の根でない場合、根になるよう更新される
            return data[x];
        }
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    int size(int x) {
        return -data[find(x)];
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n, m;
    cin >> n >> m;

    vector<ll> xs, ys;
    xs.push_back(0);
    ys.push_back(0);

    vector<ll> a(n), b(n), c(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i] >> b[i] >> c[i];
        xs.push_back(a[i]);
        xs.push_back(b[i]);
        ys.push_back(c[i]);
    }

    vector<ll> d(m), e(m), f(m);
    for (int i = 0; i < m; i++) {
        cin >> d[i] >> e[i] >> f[i];
        xs.push_back(d[i]);
        ys.push_back(e[i]);
        ys.push_back(f[i]);
    }

    xs.push_back(-INF);
    xs.push_back(INF);
    ys.push_back(-INF);
    ys.push_back(INF);

    map<ll, int> zip_x, zip_y;
    int sz_x = compress(xs, zip_x);
    int sz_y = compress(ys, zip_y);

    vector< vector<int> > banx(sz_x + 1, vector<int>(sz_y + 1, 0));
    for (int i = 0; i < n; i++) {
        int x1 = zip_x[a[i]];
        int x2 = zip_x[b[i]];
        int y = zip_y[c[i]];
        banx[x1 + 1][y]++;
        banx[x2 + 1][y]--;
    }

    for (int j = 0; j < sz_y; j++) {
        for (int i = 1; i < sz_x; i++) {
            banx[i][j] += banx[i - 1][j];
        }
    }

    vector< vector<int> > bany(sz_x + 1, vector<int>(sz_y + 1, 0));
    for (int i = 0; i < m; i++) {
        int x = zip_x[d[i]];
        int y1 = zip_y[e[i]];
        int y2 = zip_y[f[i]];
        bany[x][y1 + 1]++;
        bany[x][y2 + 1]--;
    }

    for (int i = 0; i < sz_x; i++) {
        for (int j = 1; j < sz_y; j++) {
            bany[i][j] += bany[i][j - 1];
        }
    }

    UnionFind uf(sz_x * sz_y);
    for (int i = 1; i < sz_x; i++) {
        for (int j = 1; j < sz_y; j++) {
            if (j + 1 < sz_y) {
                if (!banx[i][j]) {
                    uf.unite(i * sz_y + j, i * sz_y + j + 1);
                }
            }

            if (i + 1 < sz_x) {
                if (!bany[i][j]) {
                    uf.unite(i * sz_y + j, (i + 1) * sz_y + j);
                }
            }
        }
    }

    int sx = zip_x[0], sy = zip_y[0];

    ll ans = 0;
    for (int i = 1; i < sz_x; i++) {
        for (int j = 1; j < sz_y; j++) {
            if (uf.same(i * sz_y + j, sx * sz_y + sy)) {
                if (abs(xs[i]) == INF || abs(xs[i - 1]) == INF || abs(ys[j]) == INF || abs(ys[j - 1]) == INF) {
                    cout << "INF\n";
                    return 0;
                }
                ans += (xs[i] - xs[i - 1]) * (ys[j] - ys[j - 1]);
            }
        }
    }
    cout << ans << newl;

    return 0;
}


Measured memory_bytes: 109600