
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
typedef tuple<int, int, int> iii;

const int N = 3e3 + 5;
int n, m;
ll res;
bool grid[N][N][4];
bool visited[N][N];

struct seg {
    int L, R, x;
};

int main() {
    // freopen("in2.txt", "r", stdin);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> m;
    vector<seg> v(n); // vertical input
    vector<seg> h(m); // horizontal input
    unordered_set<int> V; // vertical set
    unordered_set<int> H; // horizontal set
    for (int i = 0; i < n; ++i) {
        cin >> v[i].L >> v[i].R >> v[i].x;
        H.insert(v[i].L);
        H.insert(v[i].R);
        V.insert(v[i].x);
    }
    for (int i = 0; i < m; ++i) {
        cin >> h[i].x >> h[i].L >> h[i].R;
        V.insert(h[i].L);
        V.insert(h[i].R);
        H.insert(h[i].x);
    }
    vector<int> vl(V.begin(), V.end());
    vector<int> hl(H.begin(), H.end());
    vl.push_back(INT_MIN);
    vl.push_back(INT_MAX);
    hl.push_back(INT_MIN);
    hl.push_back(INT_MAX);
    sort(vl.begin(), vl.end());
    sort(hl.begin(), hl.end());
    int r = hl.size() - 1; // max grid r
    int c = vl.size() - 1; // max grid c

    // split up / down
    for (auto s : h) {
        int L = s.L, R = s.R, x = s.x;
        int idx0 = lower_bound(vl.begin(), vl.end(), L) - vl.begin();
        int idx1 = lower_bound(vl.begin(), vl.end(), R) - vl.begin();
        int idx = lower_bound(hl.begin(), hl.end(), x) - hl.begin();
        for (int k = idx0; k < idx1; ++k) {
            grid[idx - 1][k][1] = grid[idx][k][3] = true;
        }
    }
    // split left / right
    for (auto s : v) {
        int L = s.L, R = s.R, x = s.x;
        int idx0 = lower_bound(hl.begin(), hl.end(), L) - hl.begin();
        int idx1 = lower_bound(hl.begin(), hl.end(), R) - hl.begin();
        int idx = lower_bound(vl.begin(), vl.end(), x) - vl.begin();
        for (int k = idx0; k < idx1; ++k) {
            grid[k][idx - 1][0] = grid[k][idx][2] = true;
        }
    }

    vector<iii> dxy = {{1,0,1}, {-1,0,3}, {0,1,0}, {0,-1,2}};
    queue<ii> que;
    int sx = lower_bound(hl.begin(), hl.end(), 0) - hl.begin() - 1;
    int sy = lower_bound(vl.begin(), vl.end(), 0) - vl.begin() - 1;
    que.push({sx, sy});
    visited[sx][sy] = true;
    bool ok = true;
    while (!que.empty()) {
        auto [x, y] = que.front(); que.pop();
        res += 1LL * (hl[x + 1] - hl[x]) * (vl[y + 1] - vl[y]);
        if (res)
        for (auto [dx, dy, dir] : dxy) {
            int nx = x + dx;
            int ny = y + dy;
            if (grid[x][y][dir]) {
                continue; // block
            }
            if (nx == 0 || ny == 0 || nx == r || ny == c) {
                ok = false;
                continue;
            }
            if (visited[nx][ny]) continue;
            visited[nx][ny] = true;
            que.push({ nx, ny });
        }
    }
    if (!ok)
        cout << "INF" << endl;
    else
        cout << res << endl;


    return 0;
}

