use std::io::{stdin, Read};

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: ty),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    parse!(it, n: usize, m: usize);
    let mut sx = vec![0];
    let mut sy = vec![0];
    let mut lh = vec![];
    let mut lv = vec![];
    for _ in 0..n {
        parse!(it, a: i64, b: i64, c: i64);
        lh.push((a, b, c));
        sx.push(a);
        sx.push(b);
        sy.push(c);
    }

    for _ in 0..m {
        parse!(it, c: i64, a: i64, b: i64);
        lv.push((a, b, c));
        sy.push(a);
        sy.push(b);
        sx.push(c);
    }

    sx.sort();
    sx.dedup();
    let xs = sx
        .iter()
        .enumerate()
        .map(|(i, &x)| (x, i))
        .collect::<std::collections::HashMap<_, _>>();
    sy.sort();
    sy.dedup();
    let ys = sy
        .iter()
        .enumerate()
        .map(|(i, &x)| (x, i))
        .collect::<std::collections::HashMap<_, _>>();

    let w = sx.len() * 2;
    let h = sy.len() * 2;

    let mut d = vec![vec![Unseen; w]; h];
    for &(a, b, c) in lh.iter() {
        let y = ys[&c] * 2;
        for i in (xs[&a] * 2)..=(xs[&b] * 2) {
            d[y][i] = Wall;
        }
    }

    for &(a, b, c) in lv.iter() {
        let x = xs[&c] * 2;
        for i in (ys[&a] * 2)..=(ys[&b] * 2) {
            d[i][x] = Wall;
        }
    }

    let mut q = std::collections::VecDeque::new();
    let (x, y) = (xs[&0] * 2, ys[&0] * 2);
    q.push_back((x, y));
    d[x][y] = Seen;
    let dx = [0, 1, 0, -1];
    let dy = [1, 0, -1, 0];
    while let Some((x, y)) = q.pop_front() {
        for i in 0..4 {
            let nx = (x as i64) + dx[i];
            let ny = (y as i64) + dy[i];
            if nx < 0 || nx >= (w as i64) || ny < 0 || ny >= (h as i64) {
                continue;
            }
            let nx = nx as usize;
            let ny = ny as usize;
            if d[ny][nx] != Unseen {
                continue;
            }
            d[ny][nx] = Seen;
            q.push_back((nx, ny));
        }
    }

    let mut ret = 0;
    for x in 0..w {
        for y in 0..h {
            if (x == 0 || x == w - 1 || y == h - 1 || y == 0) && d[y][x] == Seen {
                println!("INF");
                return;
            }
            if x % 2 == 0 || y % 2 == 0 {
                continue;
            }
            if d[y][x] == Seen {
                ret += 1;
            }
        }
    }
    println!("{}", ret);
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum Cell {
    Wall,
    Unseen,
    Seen,
}
use Cell::*;

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        5 6
1 2 0
0 1 1
0 2 2
-3 4 -1
-2 6 3
1 0 1
0 1 2
2 0 2
-1 -4 5
3 -2 4
1 2 4
        ";
        solve(s);
    }
}
