n, m = read_line.split.map(&.to_i64)
xsets = Set(Int64).new
ysets = Set(Int64).new
vers = [] of Tuple(Int64, Int64, Int64)
hors = [] of Tuple(Int64, Int64, Int64)
n.times do
  a, b, c = read_line.split.map(&.to_i64)
  ysets << a
  ysets << b
  xsets << c
  vers << {a, b, c}
end
m.times do
  d, e, f = read_line.split.map(&.to_i64)
  ysets << d
  xsets << e
  xsets << f
  hors << {d, e, f}
end

xs = xsets.to_a.sort!
ys = ysets.to_a.sort!
w = xs.size.to_i64 + 1
h = ys.size.to_i64 + 1

alias XY = Tuple(Int64, Int64)

nodes = Hash(XY, Array(XY)).new do |h, k|
  h[k] = [] of XY
end
w.times do |x|
  h.times do |y|
    if x - 1 >= 0
      nodes[{x, y}] << {x - 1, y}
    end
    if x + 1 < w
      nodes[{x, y}] << {x + 1, y}
    end
    if y - 1 >= 0
      nodes[{x, y}] << {x, y - 1}
    end
    if y + 1 < h
      nodes[{x, y}] << {x, y + 1}
    end
  end
end

vers.each do |(a, b, c)|
  ai = ys.bsearch_index {|y| y >= a}.not_nil!.to_i64
  bi = ys.bsearch_index {|y| y >= b}.not_nil!.to_i64
  ci = xs.bsearch_index {|x| x >= c}.not_nil!.to_i64
  (ai + 1).upto(bi) do |yi|
    nodes[{ci, yi}].delete({ci + 1, yi})
    nodes[{ci + 1, yi}].delete({ci, yi})
  end
end

hors.each do |(d, e, f)|
  di = ys.bsearch_index {|y| y >= d}.not_nil!.to_i64
  ei = xs.bsearch_index {|x| x >= e}.not_nil!.to_i64
  fi = xs.bsearch_index {|x| x >= f}.not_nil!.to_i64
  (ei + 1).upto(fi) do |xi|
    nodes[{xi, di}].delete({xi, di + 1})
    nodes[{xi, di + 1}].delete({xi, di})
  end
end

startx = xs.bsearch_index {|x| x > 0}.not_nil!.to_i64
starty = ys.bsearch_index {|y| y > 0}.not_nil!.to_i64

queue = Deque(XY).new
queue << {startx, starty}
visited = Set(XY).new
visited << {startx, starty}
ans = 0_i64
until queue.empty?
  x, y = queue.shift
  if x == 0 || y == 0
    puts "INF"
    exit
  end
  ans += (xs[x] - xs[x - 1]) * (ys[y] - ys[y - 1])
  nodes[{x, y}].each do |child|
    next if visited.includes?(child)
    queue << child
    visited << child
  end
end
p ans
