#include <iostream>
#include <utility>
#include <tuple>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <numeric>
#include <queue>
#include <cmath>
#include <iomanip>
#include <array>
#include <string>
struct Coordinate {
	int x, y;
	Coordinate operator+(const Coordinate& that) const {
		return Coordinate{ x + that.x, y + that.y };
	}
};
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<std::tuple<int, int, int>> vertical(n), horizontal(m);
	for (auto& t : vertical) std::cin >> std::get<0>(t) >> std::get<1>(t) >> std::get<2>(t);
	for (auto& t : horizontal) std::cin >> std::get<0>(t) >> std::get<1>(t) >> std::get<2>(t);
	std::vector<int> x{ INT_MIN, 0, INT_MAX }, y{ INT_MIN, 0, INT_MAX };
	for (const auto& t : vertical) {
		x.push_back(std::get<0>(t));
		x.push_back(std::get<1>(t));
		y.push_back(std::get<2>(t));
	}
	for (const auto& t : horizontal) {
		x.push_back(std::get<0>(t));
		y.push_back(std::get<1>(t));
		y.push_back(std::get<2>(t));
	}
	std::sort(x.begin(), x.end()); std::sort(y.begin(), y.end());
	x.erase(std::unique(x.begin(), x.end()), x.end());
	y.erase(std::unique(y.begin(), y.end()), y.end());
	std::unordered_map<int, int> x_map, y_map;
	for (auto i = 0; i < x.size(); ++i) x_map[x[i]] = i;
	for (auto i = 0; i < y.size(); ++i) y_map[y[i]] = i;
	std::vector<std::vector<int>> barriers(x.size(), std::vector<int>(y.size(), 0));
	for (const auto& t : vertical) {
		const auto until = x_map[std::get<1>(t)];
		const auto j = y_map[std::get<2>(t)];
		for (auto from = x_map[std::get<0>(t)]; from < until; ++from) {
			barriers[from][j] |= 1;
			barriers[from][j - 1] |= 2;
		}
	}
	for (const auto& t : horizontal) {
		const auto until = y_map[std::get<2>(t)];
		const auto i = x_map[std::get<0>(t)];
		for (auto from = y_map[std::get<1>(t)]; from < until; ++from) {
			barriers[i][from] |= 4;
			barriers[i - 1][from] |= 8;
		}
	}
	std::array<Coordinate, 4> diff{ Coordinate{0, -1}, Coordinate{0, 1}, Coordinate{-1, 0}, Coordinate{1, 0} };
	std::queue<Coordinate> queue; queue.push(Coordinate{ x_map[0], y_map[0] });
	std::vector<std::vector<bool>> visit(x.size(), std::vector<bool>(y.size(), false)); visit[x_map[0]][y_map[0]] = true;
	while (!queue.empty()) {
		const auto top = queue.front(); queue.pop();
		for (auto i = 0; i < diff.size(); ++i) if ((barriers[top.x][top.y] & (1 << i)) == 0) {
			const auto next = top + diff[i];
			if (0 <= next.x && next.x < visit.size() && 0 <= next.y && next.y < visit[next.x].size() && !visit[next.x][next.y]) {
				visit[next.x][next.y] = true;
				queue.push(next);
			}
		}
	}
	bool is_inf{ false };
	for (auto i = 0; i < visit.size(); ++i) {
		is_inf |= visit[i].front() || visit[i].back();
	}
	for (auto i = 0; i < visit.front().size(); ++i) {
		is_inf |= visit.front()[i] || visit.back()[i];
	}
	if (is_inf) {
		std::cout << "INF\n"; return 0;
	}
	long long int result{ 0 };
	for (auto i = 0; i < visit.size(); ++i) {
		for (auto j = 0; j < visit[i].size(); ++j) if (visit[i][j]) {
			result += ((long long int)x[i + 1] - x[i]) * ((long long int)y[j + 1] - y[j]);
		}
	}
	std::cout << result << '\n';
}

Measured memory_bytes: 40540