import sys
from typing import Iterable, Tuple, Union

class nd (object):
	getter = (
		lambda a, i: a,
		lambda a, i: a[i[0]],
		lambda a, i: a[i[0]][i[1]],
		lambda a, i: a[i[0]][i[1]][i[2]],
		lambda a, i: a[i[0]][i[1]][i[2]][i[3]],
		lambda a, i: a[i[0]][i[1]][i[2]][i[3]][i[4]],
		lambda a, i: a[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]],
	)
	class _setter (object):
		def __getitem__(self, n : int):
			setter_getter = nd.getter[n-1]
			def setter(a, i, v):
				setter_getter(a, i[:-1])[i[-1]] = v
			return setter
	setter = _setter()
	initializer = (
		lambda s, v: [v] * s,
		lambda s, v: [v] * s[0],
		lambda s, v: [[v] * s[1] for _ in range(s[0])],
		lambda s, v: [[[v] * s[2] for _ in range(s[1])] for _ in range(s[0])],
		lambda s, v: [[[[v] * s[3] for _ in range(s[2])] for _ in range(s[1])] for _ in range(s[0])],
		lambda s, v: [[[[[v] * s[4] for _ in range(s[3])] for _ in range(s[2])] for _ in range(s[1])] for _ in range(s[0])],
		lambda s, v: [[[[[[v] * s[5] for _ in range(s[4])] for _ in range(s[3])] for _ in range(s[2])] for _ in range(s[1])] for _ in range(s[0])],
	)
	shape_getter = (
		lambda a: len(a),
		lambda a: (len(a),),
		lambda a: (len(a), len(a[0])),
		lambda a: (len(a), len(a[0]), len(a[0][0])),
		lambda a: (len(a), len(a[0]), len(a[0][0]), len(a[0][0][0])),
		lambda a: (len(a), len(a[0]), len(a[0][0]), len(a[0][0][0]), len(a[0][0][0][0])),
		lambda a: (len(a), len(a[0]), len(a[0][0]), len(a[0][0][0]), len(a[0][0][0][0]), len(a[0][0][0][0][0])),
	)
	indices_iterator = (
		lambda s: iter(range(s)),
		lambda s: ((i,) for i in range(s[0])),
		lambda s: ((i, j) for j in range(s[1]) for i in range(s[0])),
		lambda s: ((i, j, k) for k in range(s[2]) for j in range(s[1]) for i in range(s[0])),
		lambda s: ((i, j, k, l) for l in range(s[3]) for k in range(s[2]) for j in range(s[1]) for i in range(s[0])),
		lambda s: ((i, j, k, l, m) for m in range(s[4]) for l in range(s[3]) for k in range(s[2]) for j in range(s[1]) for i in range(s[0])),
		lambda s: ((i, j, k, l, m, n) for n in range(s[5]) for m in range(s[4]) for l in range(s[3]) for k in range(s[2]) for j in range(s[1]) for i in range(s[0])),
	)
	iterable_product = (
		lambda s: iter(s),
		lambda s: ((i,) for i in s[0]),
		lambda s: ((i, j) for j in s[1] for i in s[0]),
		lambda s: ((i, j, k) for k in s[2] for j in s[1] for i in s[0]),
		lambda s: ((i, j, k, l) for l in s[3] for k in s[2] for j in s[1] for i in s[0]),
		lambda s: ((i, j, k, l, m) for m in s[4] for l in s[3] for k in s[2] for j in s[1] for i in s[0]),
		lambda s: ((i, j, k, l, m, n) for n in s[5] for m in s[4] for l in s[3] for k in s[2] for j in s[1] for i in s[0]),
	)
	
	@classmethod
	def full(cls, fill_value, shape : Union[int, Tuple[int], Iterable[int]]):
		if isinstance(shape, int):
			return cls.initializer[0](shape, fill_value)
		elif not isinstance(shape, tuple):
			shape = tuple(shape)
		return cls.initializer[len(shape)](shape, fill_value)
	
	@classmethod
	def fromiter(cls, iterable : Iterable, ndim=1):
		if ndim == 1:
			return list(iterable)
		else:
			return list(map(cls.fromiter, iterable))
	
	@classmethod
	def nones(cls, shape : Union[int, Tuple[int], Iterable[int]]):
		return cls.full(None, shape)
	
	@classmethod
	def zeros(cls, shape : Union[int, Tuple[int], Iterable[int]], type=int):
		return cls.full(type(0), shape)
	
	@classmethod
	def ones(cls, shape : Union[int, Tuple[int], Iterable[int]], type=int):
		return cls.full(type(1), shape)
	
	class _range (object):
		def __getitem__(self, shape : Union[int, slice, Tuple[Union[int, slice]]]):
			if isinstance(shape, int):
				return iter(range(shape))
			elif isinstance(shape, slice):
				return iter(range(shape.stop)[shape])
			else:
				shape = tuple(range(s.stop)[s] for s in shape)
				return nd.iterable_product[len(shape)](shape)
		def __call__(self, shape : Union[int, slice, Tuple[Union[int, slice]]]):
			return self[shape]
	range = _range()


def bytes_to_str(x : bytes):
	return x.decode('utf-8')

def inputs(func=bytes_to_str, sep=None, maxsplit=-1):
	return map(func, sys.stdin.buffer.readline().split(sep=sep, maxsplit=maxsplit))

def inputs_1d(func=bytes_to_str, **kwargs):
	return nd(inputs(func, **kwargs))

def inputs_2d(nrows : int, func=bytes_to_str, **kwargs):
	return nd.fromiter(
		(inputs(func, **kwargs) for _ in range(nrows)),
		ndim=2
	)

def inputs_2d_T(nrows : int, func=bytes_to_str, **kwargs):
	return nd.fromiter(
		zip(*(inputs(func, **kwargs) for _ in range(nrows))),
		ndim=2
	)

from collections import deque
from typing import Optional


class BreadthFirstSearch (object):
	__slots__ = [
		'shape',
		'pushed',
		'_deque',
		'_getter',
		'_setter'
	]
	
	def __init__(self, shape : Union[int, Iterable[int]]):
		self.shape = (shape,) if isinstance(shape, int) else tuple(shape)
		self.pushed = nd.zeros(self.shape, type=bool)
		self._deque = deque()
		self._getter = nd.getter[len(self.shape)]
		self._setter = nd.setter[len(self.shape)]
	
	def push(self, position : Tuple[int]):
		if not self._getter(self.pushed, position):
			self._setter(self.pushed, position, True)
			self._deque.append(position)
	
	def peek(self) -> Optional[Tuple[int]]:
		return self._deque[0] if self._deque else None
	
	def pop(self) -> Optional[Tuple[int]]:
		return self._deque.popleft() if self._deque else None
	
	def __bool__(self):
		return bool(self._deque)

from bisect import bisect_left, bisect_right


N, M = inputs(int)
A, B, C = inputs_2d_T(N, int)
D, E, F = inputs_2d_T(M, int)
xs = sorted(set(C))
ys = sorted(set(D))

x_guard = nd.zeros((len(xs)+1, len(ys)+1), type=bool)
y_guard = nd.zeros((len(xs)+1, len(ys)+1), type=bool)

for a, b, c in zip(A, B, C):
	c = bisect_right(xs, c)
	a = bisect_left(ys, a) + 1
	b = bisect_right(ys, b)
	for y in range(a, b):
		x_guard[c][y] = True

for d, e, f in zip(D, E, F):
	d = bisect_right(ys, d)
	e = bisect_left(xs, e) + 1
	f = bisect_right(xs, f)
	for x in range(e, f):
		y_guard[x][d] = True

cow = (
	bisect_right(xs, 0),
	bisect_right(ys, 0)
)

bfs = BreadthFirstSearch(shape=(len(xs)+1, len(ys)+1))
bfs.push(cow)

area = 0
while bfs:
	xi, yi = bfs.pop()
	
	if 0 < xi < len(xs) and 0 < yi < len(ys):
		area += (xs[xi] - xs[xi-1]) * (ys[yi] - ys[yi-1])
		if not x_guard[xi][yi]:
			bfs.push((xi-1, yi))
		if not x_guard[xi+1][yi]:
			bfs.push((xi+1, yi))
		if not y_guard[xi][yi]:
			bfs.push((xi, yi-1))
		if not y_guard[xi][yi+1]:
			bfs.push((xi, yi+1))
	else:
		area = 'INF'
		break

print(area)

