//---------- begin union_find ----------
#[allow(dead_code)]
mod union_find {
    pub struct UF {
        p: Vec<i32>,
    }
    impl UF {
        pub fn new(n: usize) -> UF {
            UF {p: vec![-1; n] }
        }
        pub fn init(&mut self) {
            for p in self.p.iter_mut() {
                *p = -1;
            }
        }
        pub fn root(&mut self, mut x: usize) -> usize {
            while self.p[x] >= 0 {
                let p = self.p[x] as usize;
                if self.p[p] < 0 {
                    return p;
                }
                let q = self.p[p] as usize;
                self.p[x] = q as i32;
                x = q;
            }
            x
        }
        pub fn same(&mut self, x: usize, y: usize) -> bool {
            self.root(x) == self.root(y)
        }
        pub fn unite(&mut self, mut x: usize, mut y: usize) -> Option<(usize, usize)> {
            x = self.root(x);
            y = self.root(y);
            if x == y {
                return None;
            }
            if self.p[x] > self.p[y] {
                let s = x;
                x = y;
                y = s;
            }
            self.p[x] += self.p[y];
            self.p[y] = x as i32;
            Some((x, y))
        }
        pub fn parent(&mut self, x: usize) -> Option<usize> {
            let p = self.p[x];
            if p >= 0 {
                Some(p as usize)
            } else {
                None
            }
        }
        pub fn get_size(&mut self, x: usize) -> usize {
            let r = self.root(x);
            (-self.p[r]) as usize
        }
    }
}
//---------- end union_find ----------

fn run() {
    proconio::input! {
        n: usize,
        m: usize,
        mut col: [(i64, i64, i64); n],
        mut row: [(i64, i64, i64); m],
    }
    for p in row.iter_mut().chain(col.iter_mut()) {
        p.0 = 2 * p.0 + 1;
        p.1 = 2 * p.1 + 1;
        p.2 = 2 * p.2 + 1;
    }
    let inf = 2_000_000_000 + 3;
    let mut x = vec![inf, -inf];
    let mut y = vec![inf, -inf];
    for &(_, _, c) in col.iter() {
        y.push(c);
    }
    for &(d, _, _) in row.iter() {
        x.push(d);
    }
    x.sort();
    x.dedup();
    y.sort();
    y.dedup();
    let h = x.len() - 1;
    let w = y.len() - 1;
    let mut u = union_find::UF::new(h * w);
    for (i, x) in x.iter().enumerate().skip(1) {
        if *x == inf {
            break;
        }
        let mut imos = vec![0; w];
        for &(_, e, f) in row.iter().filter(|p| p.0 == *x) {
            let l = match y.binary_search(&e) {
                Ok(k) => k,
                Err(k) => k,
            };
            let r = match y.binary_search(&f) {
                Ok(k) => k,
                Err(k) => k - 1,
            };
            if l < r {
                imos[l] += 1;
                imos[r] -= 1;
            }
        }
        for j in 1..w {
            imos[j] += imos[j - 1];
        }
        for (j, _) in imos.iter().enumerate().filter(|c| *c.1 == 0) {
            u.unite((i - 1) * w + j, i * w + j);
        }
    }
    for (j, y) in y.iter().enumerate().skip(1) {
        if *y == inf {
            break;
        }
        let mut imos = vec![0; h];
        for &(a, b, _) in col.iter().filter(|p| p.2 == *y) {
            let l = match x.binary_search(&a) {
                Ok(k) => k,
                Err(k) => k,
            };
            let r = match x.binary_search(&b) {
                Ok(k) => k,
                Err(k) => k - 1,
            };
            if l < r {
                imos[l] += 1;
                imos[r] -= 1;
            }
        }
        for j in 1..h {
            imos[j] += imos[j - 1];
        }
        for (i, _) in imos.iter().enumerate().filter(|c| *c.1 == 0) {
            u.unite(i * w + j - 1, i * w + j);
        }
    }
    let mut p = 0;
    while x[p + 1] <= 0 {
        p += 1;
    }
    let mut q = 0;
    while y[q + 1] <= 0 {
        q += 1;
    }
    let root = u.root(p * w + q);
    let mut ans = 0;
    for (i, x) in x.windows(2).map(|x| (x[1] - x[0]) / 2).enumerate() {
        for (j, y) in y.windows(2).map(|y| (y[1] - y[0]) / 2).enumerate() {
            if u.root(i * w + j) == root {
                if i == 0 || i == h - 1 || j == 0 || j == w - 1 {
                    println!("INF");
                    return;
                }
                ans += x * y;
            }
        }
    }
    println!("{}", ans);
}

fn main() {
    run();
}


Measured memory_bytes: 6016