struct Scanner {
	handle: std::io::Stdin,
	buffer: std::collections::VecDeque<String>
}

impl Scanner {
	pub fn new() -> Scanner {
		Scanner {
			handle: std::io::stdin(),
			buffer: std::collections::VecDeque::new()
		}
	}
	pub fn next<T: std::str::FromStr>(&mut self) -> Result<T, T::Err> {
		if self.buffer.len() == 0 {
			loop {
				let mut available = String::new();
				self.handle.read_line(&mut available).unwrap();
				self.buffer = available.split_whitespace().map(String::from).collect();
				if self.buffer.len() > 0 {
					break;
				}
			}
		}
		T::from_str(&self.buffer.pop_front().unwrap())
	}
}

fn main() {
	let mut scanner = Scanner::new();
	let n: isize = scanner.next().unwrap();
	let m: isize = scanner.next().unwrap();
	let mut hmin = isize::max_value();
	let mut hmax = isize::min_value();
	let mut vlines = Vec::new();
	for _ in 0..n {
		let a: isize = scanner.next().unwrap();
		let b: isize = scanner.next().unwrap();
		let c: isize = scanner.next().unwrap();
		hmin = std::cmp::min(hmin, c);
		hmax = std::cmp::max(hmax, c);
		vlines.push((a,b,c));
	}
	let mut vmin = isize::max_value();
	let mut vmax = isize::min_value();
	let mut hlines = Vec::new();
	for _ in 0..m {
		let d: isize = scanner.next().unwrap();
		let e: isize = scanner.next().unwrap();
		let f: isize = scanner.next().unwrap();
		vmin = std::cmp::min(vmin, d);
		vmax = std::cmp::max(vmax, d);
		hlines.push((d,e,f));
	}
	if hmin > 0 || hmax < 0 || vmin > 0 || vmax < 0 {
		println!("INF");
		return;
	}

	let mut vpoints = std::collections::BTreeSet::<isize>::new();
	let mut hpoints = std::collections::BTreeSet::<isize>::new();
	vpoints.insert(0);
	vpoints.insert(0);
	for &(a,b,c) in vlines.iter() {
		vpoints.insert(a);
		vpoints.insert(b);
		hpoints.insert(c);
	}
	for &(d,e,f) in hlines.iter() {
		vpoints.insert(d);
		hpoints.insert(e);
		hpoints.insert(f);
	}
	vmin -= 1; vpoints.insert(vmin);
	vmax += 1; vpoints.insert(vmax);
	hmin -= 1; hpoints.insert(hmin);
	hmax += 1; hpoints.insert(hmax);

	let vpoints: Vec<isize> = vpoints.iter().cloned().collect();
	let hpoints: Vec<isize> = hpoints.iter().cloned().collect();
	// println!("vpoints: {:?}", vpoints);
	// println!("hpoints: {:?}", hpoints);

	let iv0 = vpoints.binary_search(&&0).unwrap();
	let ih0 = hpoints.binary_search(&&0).unwrap();

	let mut grid = vec![
		vec![
			(false,false,false,false,false); // area, left, down, up, right
			hpoints.len()
		]; 
		vpoints.len()
	];
	for (a,b,c) in vlines.iter() {
		let ivlow = vpoints.binary_search(&a).unwrap();
		let ivhigh = vpoints.binary_search(&b).unwrap();
		let ih = hpoints.binary_search(&c).unwrap();
		for i in ivlow..ivhigh {
			grid[i][ih-1].4 = true;
			grid[i][ih].1 = true;
		}
	}
	for (d,e,f) in hlines.iter() {
		// println!("{:?}", (d,e,f));
		let iv = vpoints.binary_search(&d).unwrap();
		let ihlow = hpoints.binary_search(&e).unwrap();
		let ihhigh = hpoints.binary_search(&f).unwrap();
		for i in ihlow..ihhigh {
			grid[iv-1][i].2 = true;
			grid[iv][i].3 = true;
		}
	}
	let mut bfsq = std::collections::VecDeque::new();
	let mut area = 0;
	bfsq.push_back((iv0, ih0)); grid[iv0][ih0].0 = true;
	bfsq.push_back((iv0-1, ih0)); grid[iv0-1][ih0].0 = true;
	bfsq.push_back((iv0, ih0-1)); grid[iv0][ih0-1].0 = true;
	bfsq.push_back((iv0-1, ih0-1)); grid[iv0-1][ih0-1].0 = true;
	while !bfsq.is_empty() {
		// println!("bfsq: {:?}", bfsq);
		let (iv,ih) = bfsq.pop_front().unwrap();
		// let c = &grid[iv][ih];
		if (hpoints[ih] == hmin && !grid[iv][ih].1) 
		|| (vpoints[iv+1] == vmax && !grid[iv][ih].2) 
		|| (vpoints[iv] == vmin && !grid[iv][ih].3) 
		|| (hpoints[ih+1] == hmax && !grid[iv][ih].4) {
			println!("INF");
			return;	
		}
		grid[iv][ih].0 = true;
		area += (vpoints[iv+1]-vpoints[iv])*(hpoints[ih+1]-hpoints[ih]);
		// let c = &grid[iv][ih];
		// let cl = &grid[iv][ih-1];
		// let cd = &grid[iv+1][ih];
		// let cu = &grid[iv-1][ih];
		// let cr = &grid[iv][ih+1];
		// println!("{:?}: {:?}",(iv,ih),grid[iv][ih]);
		if !grid[iv][ih].1 && !grid[iv][ih-1].0 {
			// println!("inserting {:?}",(iv,ih-1));
			bfsq.push_back((iv,ih-1));
			grid[iv][ih-1].0 = true;
		}
		if !grid[iv][ih].2 && !grid[iv+1][ih].0 {
			// println!("inserting {:?}",(iv+1,ih));
			bfsq.push_back((iv+1,ih));
			grid[iv+1][ih].0 = true;
		}
		if !grid[iv][ih].3 && !grid[iv-1][ih].0 {
			// println!("inserting {:?}",(iv-1,ih));
			bfsq.push_back((iv-1,ih));
			grid[iv-1][ih].0 = true;
		}
		if !grid[iv][ih].4 && !grid[iv][ih+1].0 {
			// println!("inserting {:?}",(iv,ih+1));
			bfsq.push_back((iv,ih+1));
			grid[iv][ih+1].0 = true;
		}
	}
	println!("{}", area);
}
