#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define REP(i, n) for (int i = 0; i < n; i++)
#define ALL(a) (a).begin(), (a).end()
typedef vector<int> vi;
const int INF = 1LL << 60; //10e18+10e17ちょっとくらい
const int MOD = 1000000007;
const int MAX_N = 200100;

//座標圧縮後の軸の値
set<int> xaxis, yaxis;
vi itox, itoy;
//線分の有無を格納する
//点から見て大きい側と小さい側の連結情報を格納する
bool xwall[3010][3010][2];
bool ywall[3010][3010][2];
//訪問済みかどうか
bool grid[6010][6010];
signed main()
{
    //  以降 cin の入力元が 'input.txt' になる
    //std::ifstream in("input.txt");
    //std::cin.rdbuf(in.rdbuf());
    int N, M;
    cin >> N >> M;

    vector<pair<int, pair<int, int>>>
        xinput;
    vector<pair<int, pair<int, int>>> yinput;
    REP(i, N)
    {
        int a, b, y;
        cin >> a >> b >> y;
        yinput.push_back(make_pair(y, make_pair(a, b))); //y軸と直交
        xaxis.emplace(a);
        xaxis.emplace(b);
        yaxis.emplace(y);
    }
    REP(i, M)
    {
        int x, e, f;
        cin >> x >> e >> f;
        xinput.push_back(make_pair(x, make_pair(e, f))); //x軸と直交
        yaxis.emplace(e);
        yaxis.emplace(f);
        xaxis.emplace(x);
    }
    xaxis.emplace(0);
    yaxis.emplace(0);

    for (auto iter : xaxis)
        itox.emplace_back(iter);
    for (auto iter : yaxis)
        itoy.emplace_back(iter);

    REP(i, N)
    {
        int y = yinput[i].first;
        int xa = yinput[i].second.first;
        int xb = yinput[i].second.second;
        y = lower_bound(itoy.begin(), itoy.end(), y) - itoy.begin();
        xa = lower_bound(itox.begin(), itox.end(), xa) - itox.begin();
        xb = lower_bound(itox.begin(), itox.end(), xb) - itox.begin();
        for (int x = xa; x <= xb; x++)
        {
            if (x != xa)
                ywall[x][y][0] = true; //y軸と直交
            if (x != xb)
                ywall[x][y][1] = true; //y軸と直交
        }
    }
    REP(i, M)
    {
        int x = xinput[i].first;
        int ya = xinput[i].second.first;
        int yb = xinput[i].second.second;
        x = lower_bound(itox.begin(), itox.end(), x) - itox.begin();
        ya = lower_bound(itoy.begin(), itoy.end(), ya) - itoy.begin();
        yb = lower_bound(itoy.begin(), itoy.end(), yb) - itoy.begin();
        for (int y = ya; y <= yb; y++)
        {
            if (y != ya)
                xwall[x][y][0] = true; //x軸と直交
            if (y != yb)
                xwall[x][y][1] = true; //x軸と直交
        }
    }

    int start_x = lower_bound(itox.begin(), itox.end(), 0) - itox.begin();
    int start_y = lower_bound(itoy.begin(), itoy.end(), 0) - itoy.begin();

    queue<pair<int, int>> q;
    q.push(make_pair(start_x, start_y));
    int ans = 0;
    while (!q.empty())
    {
        int x = q.front().first;
        int y = q.front().second;
        if (x < 0 || y < 0 || x > itox.size() - 2 || y > itoy.size() - 2)
        {
            cout << "INF" << endl;
            return 0;
        }
        q.pop();
        if (grid[x][y])
            continue;
        grid[x][y] = true;
        ans += (itox[x + 1] - itox[x]) * (itoy[y + 1] - itoy[y]);

        if (!(xwall[x][y][1] && xwall[x][y + 1][0]))
            q.push(make_pair(x - 1, y));
        if (!(xwall[x + 1][y][1] && xwall[x + 1][y + 1][0]))
            q.push(make_pair(x + 1, y));
        if (!(ywall[x][y][1] && ywall[x + 1][y][0]))
            q.push(make_pair(x, y - 1));
        if (!(ywall[x][y + 1][1] && ywall[x + 1][y + 1][0]))
            q.push(make_pair(x, y + 1));
    }
    cout << ans << endl;

    return 0;
}

Measured memory_bytes: 45328