#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <vector>

struct line_t {
    std::pair<int, int> range;
    int pos;
    bool xaxis;

    line_t() {}
    line_t(std::pair<int, int> range, int pos, bool xaxis)
        : range(range)
        , pos(pos)
        , xaxis(xaxis)
    {
    }
};

int main()
{
    size_t n, m;
    std::cin >> n >> m;

    std::vector<int> xs, ys;
    std::vector<line_t> lines;

    if (n == 1 || m == 1) {
        std::cout << "INF\n";
        return 0;
    }

    for (size_t i = 0; i < n; i++) {
        int a, b, c;
        std::cin >> a >> b >> c;
        xs.push_back(a);
        xs.push_back(b);
        ys.push_back(c);
        lines.emplace_back(std::make_pair(a, b), c, true);
    }

    for (size_t i = 0; i < m; i++) {
        int d, e, f;
        std::cin >> d >> e >> f;
        xs.push_back(d);
        ys.push_back(e);
        ys.push_back(f);
        lines.emplace_back(std::make_pair(e, f), d, false);
    }

    xs.push_back(2e+9);
    xs.push_back(0);
    xs.push_back(-2e+9);
    ys.push_back(2e+9);
    ys.push_back(0);
    ys.push_back(-2e+9);

    std::sort(xs.begin(), xs.end());
    std::sort(ys.begin(), ys.end());
    //[]: i -> x
    //lowerbound: x -> i
    xs.erase(std::unique(xs.begin(), xs.end()), xs.end());
    ys.erase(std::unique(ys.begin(), ys.end()), ys.end());

    std::vector<std::vector<int>> hng(xs.size(), std::vector<int>(ys.size()));
    auto wng = hng;

    for (auto&& line : lines) {
        if (line.xaxis) {
            int ix1 = std::lower_bound(xs.begin(), xs.end(), line.range.first) - xs.begin();
            int ix2 = std::lower_bound(xs.begin(), xs.end(), line.range.second) - xs.begin();
            int iy = std::lower_bound(ys.begin(), ys.end(), line.pos) - ys.begin();
            hng[ix1][iy]++;
            hng[ix2][iy]--;
        }
        if (!line.xaxis) {
            int iy1 = std::lower_bound(ys.begin(), ys.end(), line.range.first) - ys.begin();
            int iy2 = std::lower_bound(ys.begin(), ys.end(), line.range.second) - ys.begin();
            int ix = std::lower_bound(xs.begin(), xs.end(), line.pos) - xs.begin();
            wng[ix][iy1]++;
            wng[ix][iy2]--;
        }
    }

    for (size_t i = 0; i < xs.size(); i++) {
        for (size_t j = 0; j < ys.size(); j++) {
            if (i < (xs.size() - 1))
                hng[i + 1][j] += hng[i][j];
            if (j < (ys.size() - 1))
                wng[i][j + 1] += wng[i][j];
        }
    }

    std::queue<std::pair<int, int>> search;
    std::pair<int, int> zero = { std::lower_bound(xs.begin(), xs.end(), 0) - xs.begin(),
        std::lower_bound(ys.begin(), ys.end(), 0) - ys.begin() };
    search.push(zero);

    std::vector<std::vector<int>> flag(xs.size() - 1, std::vector<int>(ys.size() - 1, 0));
    flag[zero.first][zero.second] = 1;

    long long area = 0;
    while (!search.empty()) {
        auto searching = search.front();
        if (searching.first < 1 || searching.second < 1 || searching.first >= (xs.size() - 2) || searching.second >= (ys.size() - 2)) {
            std::cout << "INF\n";
            return 0;
        }
        area += 1LL * (xs[searching.first + 1] - xs[searching.first]) * (ys[searching.second + 1] - ys[searching.second]);
        search.pop();
        if (!wng[searching.first][searching.second] && !flag[searching.first - 1][searching.second]) {
            search.push({ searching.first - 1, searching.second });
            flag[searching.first - 1][searching.second] = true;
        }
        if (!hng[searching.first][searching.second] && !flag[searching.first][searching.second - 1]) {
            search.push({ searching.first, searching.second - 1 });
            flag[searching.first][searching.second - 1] = true;
        }
        if (searching.first < (xs.size() - 2) && !wng[searching.first + 1][searching.second] && !flag[searching.first + 1][searching.second]) {
            search.push({ searching.first + 1, searching.second });
            flag[searching.first + 1][searching.second] = true;
        }
        if (searching.second < (ys.size() - 2) && !hng[searching.first][searching.second + 1] && !flag[searching.first][searching.second + 1]) {
            search.push({ searching.first, searching.second + 1 });
            flag[searching.first][searching.second + 1] = true;
        }
    }
    std::cout << area << "\n";
    return 0;
}


Measured memory_bytes: 109124