//package abc168.F

import java.io.*
import java.math.*
import java.util.*
import kotlin.math.*

var reader: BufferedReader = System.`in`.bufferedReader()
var writer: PrintWriter = PrintWriter(System.`out`)

fun next() = reader.readLine()!!
fun nextInt() = next().toInt()
fun nextLong() = next().toLong()
fun nextDouble() = next().toDouble()
fun nextStrings() = next().split(" ")
fun nextInts() = nextStrings().map { it.toInt() }
fun nextLongs() = nextStrings().map { it.toLong() }
fun nextDoubles() = nextStrings().map { it.toDouble() }

fun put(v: Any?) = writer.print(v)
fun puts() = writer.println()
fun puts(v: Any?) = writer.println(v)

var debug = false
fun dp(v: Any?) {
    if (debug) println(v)
}
fun dp() {
    if (debug) println()
}

fun <T> unique(list: List<T>): MutableList<T> {
    return TreeSet<T>(list).toMutableList()
}

class UFT(
    val N: Int
) {
    private val parent = Array<Int>(N) { it }
    private val rank = Array<Int>(N) { 0 }

    fun root(x: Int): Int {
        if (parent[x] != x) {
            parent[x] = root(parent[x])
        }
        return parent[x]
    }
    fun same(x: Int, y: Int): Boolean {
        return root(x) == root(y)
    }
    fun unite(x: Int, y: Int) {
        val rootX = root(x)
        val rootY = root(y)
        if (rootX == rootY) {
            return
        }

        if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY
        } else {
            parent[rootY] = rootX
            if (rank[rootX] == rank[rootY]) {
                ++rank[rootX]
            }
        }
    }
}

fun test(case: Int, input: String, expected: String) {
    reader = input.trimIndent().reader().buffered()

    val stringWriter = StringWriter()
    writer = PrintWriter(stringWriter)

    solve()
    writer.flush()

    val actual = stringWriter.toString()

    println("[test $case]")
    if ("${expected}" == actual) {
        println("OK")
    } else {
        println("NG")
        println()
        println("expected: \"${expected}\"")
        println("actual:   \"${actual}\"")
    }
    println()
}

fun main(args: Array<String>) {
    if ((args.size == 1) && (args[0] == "test")) {
        testAll()
    } else {
        solve()
        writer.flush()
    }
}

///////////////////////////////////////////////////////////

fun testAll() {
    debug = true

    test(1,
    """
    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
    """,
    "13")
    test(2,
    """
    6 1
    -3 -1 -2
    -3 -1 1
    -2 -1 2
    1 4 -2
    1 4 -1
    1 4 1
    3 1 4
    """,
    "INF")
}

fun <T> readToList(n: Int, transformer: (List<Long>) -> T): MutableList<T> {
    return mutableListOf<T>().also { list ->
        repeat(n) {
            val lines = nextLongs()
            list.add(transformer(lines))
        }
    }
}

class Indexer(
    val X: Int,
    val Y: Int
) {
    operator fun invoke(x: Int, y: Int): Int {
        return y * X + x
    }

    fun <T> contentToString(arr: Array<T>): String {
        val builder = StringBuilder()

        builder.appendln("----------")
        for (y in 0 until Y) {
            for (x in 0 until X) {
                builder.append(arr[this(x, y)])
                builder.append(", ")
            }
            builder.appendln()
        }
        builder.append("----------")

        return builder.toString()
    }
}

val TOP = 1
val BOTTOM = 2
val LEFT = 4
val RIGHT = 8

typealias Line = Pair<Long, Long>
typealias Point = Pair<Int, Int>

fun doSolve(): Long {

    val (N, M) = nextInts()

    var Xseries = mutableListOf<Long>()
    Xseries.add(0L)

    var Yseries = mutableListOf<Long>()
    Yseries.add(0L)

    var HLines = mutableListOf<Pair<Long, Line>>()
    var VLines = mutableListOf<Pair<Long, Line>>()

    repeat(N) {
        val (a, b, c) = nextLongs()
        Xseries.add(a)
        Xseries.add(b)
        Yseries.add(c)

        HLines.add(Pair(c, Line(a, b)))
    }

    repeat(M) {
        val (d, e, f) = nextLongs()
        Xseries.add(d)
        Yseries.add(e)
        Yseries.add(f)

        VLines.add(Pair(d, Line(e, f)))
    }

    Xseries = unique(Xseries)
    Yseries = unique(Yseries)

    //dp(Xseries)
    //dp(Yseries)

    val X = Xseries.size + 2
    val Y = Yseries.size + 2
    val index = Indexer(X, Y)

    var startX = Xseries.binarySearch(0L)
    var startY = Yseries.binarySearch(0L)

    dp("[$startX, $startY]")

    val uft = UFT(X*Y)

    run {
        val Hwalls = Array<Int>(X*Y) { 0 }
        HLines.forEach { (c, line) ->
            val (a, b) = line

            val xIdx1 = Xseries.binarySearch(a) + 1
            val xIdx2 = Xseries.binarySearch(b) + 1
            val yIdx = Yseries.binarySearch(c) + 1

            ++Hwalls[index(xIdx1, yIdx)]
            --Hwalls[index(xIdx2, yIdx)]
        }
        //dp("Hwall: ${index.contentToString(Hwalls)}")

        for (y in 1 until Y-1) {
            var Hwall = 0

            for (x in 1 until X-1) {
                Hwall += Hwalls[index(x, y)]

                if (Hwall <= 0) {
                    uft.unite(index(x, y), index(x, y-1))
                }
            }
        }
    }

    run {
        val Vwalls = Array<Int>(X*Y) { 0 }
        VLines.forEach { (d, line) ->
            val (e, f) = line

            val xIdx = Xseries.binarySearch(d) + 1
            val yIdy1 = Yseries.binarySearch(e) + 1
            val yIdy2 = Yseries.binarySearch(f) + 1

            ++Vwalls[index(yIdy1, xIdx)]
            --Vwalls[index(yIdy2, xIdx)]
        }
        //dp("Vwall: ${index.contentToString(Vwalls)}")

        for (x in 1 until X-1) {
            var Vwall = 0

            for (y in 1 until Y-1) {
                Vwall += Vwalls[index(y, x)]

                if (Vwall <= 0) {
                    uft.unite(index(x, y), index(x-1, y))
                }
            }
        }
    }

    dp()

    var area = 0L
    val visited = mutableSetOf<Point>()

    val queue = ArrayDeque<Pair<Int, Int>>()
    queue.add(Pair(startX, startY))

    val accessible = uft.root(index(startX, startY))

    while (!queue.isEmpty()) {
        val p= queue.remove()
        dp("pop: $p")
        if (!visited.add(p)) {
            continue;
        }

        val (x, y) = p
        if ((x == 0) || (x == X-1)) {
            return -1
        }
        if ((y == 0) || (y == Y-1)) {
            return -1
        }

        val a = (Xseries[x]-Xseries[x-1]) * (Yseries[y]-Yseries[y-1])
        dp("area: $a")

        area += a
        dp("-> $area")

        if (uft.root(index(x, y+1)) == accessible) {
            dp("queue: ($x, ${y+1})")
            queue.add(Point(x, y+1))
        }
        if (uft.root(index(x, y-1)) == accessible) {
            dp("queue: ($x, ${y-1})")
            queue.add(Point(x, y-1))
        }
        if (uft.root(index(x-1, y)) == accessible) {
            dp("queue: (${x-1}, $y)")
            queue.add(Point(x-1, y))
        }
        if (uft.root(index(x+1, y)) == accessible) {
            dp("queue: (${x+1}, $y)")
            queue.add(Point(x+1, y))
        }

        dp()
    }

    return area
}

fun solve() {
    val ret = doSolve()
    if (ret >= 0) {
        put(ret)
    } else {
        put("INF")
    }
}
