Problem:


Score: 600 points

Problem Statement

There is a grass field that stretches infinitely.

In this field, there is a negligibly small cow. Let (x, y) denote the point that is x\ \mathrm{cm} south and y\ \mathrm{cm} east of the point where the cow stands now. The cow itself is standing at (0, 0).

There are also N north-south lines and M east-west lines drawn on the field. The i-th north-south line is the segment connecting the points (A_i, C_i) and (B_i, C_i), and the j-th east-west line is the segment connecting the points (D_j, E_j) and (D_j, F_j).

What is the area of the region the cow can reach when it can move around as long as it does not cross the segments (including the endpoints)? If this area is infinite, print INF instead.

Constraints

All values in input are integers between -10^9 and 10^9  (inclusive).

1 \leq N, M \leq 1000

A_i < B_i\ (1 \leq i \leq N)

E_j < F_j\ (1 \leq j \leq M)

The point (0, 0) does not lie on any of the given segments.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1 C_1
:
A_N B_N C_N
D_1 E_1 F_1
:
D_M E_M F_M

Output

If the area of the region the cow can reach is infinite, print INF; otherwise, print an integer representing the area in \mathrm{cm^2}.

(Under the constraints, it can be proved that the area of the region is always an integer if it is not infinite.)

Sample Input 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

Sample Output 1

13

The area of the region the cow can reach is 13\ \mathrm{cm^2}.

Sample Input 2

6 1
-3 -1 -2
-3 -1 1
-2 -1 2
1 4 -2
1 4 -1
1 4 1
3 1 4

Sample Output 2

INF

The area of the region the cow can reach is infinite.



Sample input:
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


Sample output:
13

Submission status: Runtime Error

Solution code:
# coding: utf-8
import sys
#from operator import itemgetter
sysread = sys.stdin.readline
read = sys.stdin.read
from heapq import heappop, heappush
#from collections import defaultdict
sys.setrecursionlimit(10**7)
#import math
#from itertools import product#accumulate, combinations, product
import bisect# lower_bound etc
import numpy as np
#from copy import deepcopy
from collections import deque
def run():
    N,M, *A2F = map(int, read().split())
    A = A2F[0:3*N:3]
    B = A2F[1:3*N+1:3]
    C = A2F[2:3*N+2:3]
    D = A2F[3*N::3]
    E = A2F[3*N+1::3]
    F = A2F[3*N+2::3]

    x_list, y_list = sorted(list(set(A+B+D))), sorted(list(set(C+E+F)))
    max_sq = (x_list[-1]-x_list[0]) * (y_list[-1] - y_list[0])
    #print(x_list)
    tmp1 = np.array([x_list[0]]+x_list)
    tmp2 = np.array(x_list+[x_list[-1]])
    x_grid = tmp2 - tmp1
    #print(x_grid)
    tmp1 = np.array([y_list[0]] + y_list)
    tmp2 = np.array(y_list + [y_list[-1]])
    y_grid = tmp2 - tmp1
    #print(y_list)
    #print(y_grid)
    grid = np.dot(x_grid.reshape(-1,1), y_grid.reshape(1,-1))
    seen = np.zeros_like(grid, dtype=np.bool)
    walls = np.zeros_like(grid, dtype=np.int32)
    for a,b,c in zip(A,B,C):
        a_i = bisect.bisect_left(x_list, a)
        b_i = bisect.bisect_left(x_list, b)
        c_i = bisect.bisect_left(y_list, c)
        walls[a_i+1:b_i+1, c_i] += 1 << 1
        walls[a_i+1:b_i+1, c_i+1] += 1 << 3
    for d,e,f in zip(D,E,F):
        d_i = bisect.bisect_left(x_list, d)
        e_i = bisect.bisect_left(y_list, e)
        f_i = bisect.bisect_left(y_list, f)
        walls[d_i,e_i+1:f_i+1] += 1 << 0
        walls[d_i+1,e_i+1:f_i+1] += 1 << 2

    start_x = bisect.bisect_left(x_list, 0)
    start_y = bisect.bisect_left(y_list, 0)

    queue = deque([])
    queue.append((start_x, start_y))
    seen[start_x, start_y] = True
    max_x = len(x_list)
    max_y = len(y_list)

    ret = grid[start_x, start_y]
    while queue:
        x, y = queue.popleft()
        if x == 0 or y == 0 or x == max_x or y == max_y:
            print('INF')
            return None
        for w_i, i,j in ((1,0,1), (3,0,-1), (0,1,0),(2,-1,0)):
            if 0 <= x+i <= max_x and 0 <= y+j <= max_y:
                if not walls[x, y] & 1 << w_i:
                    if not seen[x+i, y+j]:
                        queue.append((x + i, y + j))
                        seen[x + i, y + j] = True
                        ret += grid[x + i, y + j]


    print(ret)
if __name__ == "__main__":
    run()

Submission status: Runtime Error

Solution code:
import sys
from collections import deque
input = sys.stdin.readline

N,M=map(int,input().split())
TATE=[tuple(map(int,input().split())) for i in range(N)]
YOKO=[tuple(map(int,input().split())) for i in range(M)]


T=[-1<<63,0,1<<63]
Y=[-1<<63,0,1<<63]

for a,b,c in TATE:
    T.append(a)
    T.append(b)
    Y.append(c)

for d,e,f in YOKO:
    T.append(d)
    Y.append(e)
    Y.append(f)

T=sorted(set(T))
Y=sorted(set(Y))

BT=[T[0]]
BY=[Y[0]]

for i in range(1,len(T)):
    BT.append(T[i]-T[i-1])
    BT.append(T[i])

for i in range(1,len(Y)):
    BY.append(Y[i]-Y[i-1])
    BY.append(Y[i])

TDICT=dict()
YDICT=dict()

LBT=len(BT)
LBY=len(BY)

for i in range(LBT):
    if i%2==0:
        TDICT[BT[i]]=i

for i in range(LBY):
    if i%2==0:
        YDICT[BY[i]]=i

MAP=[[0]*(LBY+1) for i in range(LBT+1)]

for a,b,c in TATE:
    t0=TDICT[a]
    t1=TDICT[b]
    y=YDICT[c]

    MAP[t0][y]+=1
    MAP[t0][y+1]-=1
    MAP[t1+1][y]-=1
    MAP[t1+1][y+1]+=1

for d,e,f in YOKO:
    t=TDICT[d]
    y0=YDICT[e]
    y1=YDICT[f]

    MAP[t][y0]+=1
    MAP[t+1][y0]-=1
    MAP[t][y1+1]-=1
    MAP[t+1][y1+1]+=1

for i in range(LBT):
    for j in range(1,LBY):
        MAP[i][j]+=MAP[i][j-1]

for i in range(LBY):
    for j in range(1,LBT):
        MAP[j][i]+=MAP[j-1][i]

#for m in MAP:
#    print(*m)

Q=deque()
x,y=TDICT[0],YDICT[0]
Q.append((x-1,y-1))
Q.append((x+1,y-1))
Q.append((x-1,y+1))
Q.append((x+1,y+1))
MAP[x-1][y-1]=MAP[x+1][y-1]=MAP[x-1][y+1]=MAP[x+1][y+1]=1
ANS=BT[x-1]*BY[y-1]+BT[x+1]*BY[y-1]+BT[x-1]*BY[y+1]+BT[x+1]*BY[y+1]

while Q:
    x,y=Q.pop()

    if MAP[x+1][y]==0 and MAP[x+2][y]==0:
        MAP[x+2][y]=1
        Q.append((x+2,y))
        ANS+=BT[x+2]*BY[y]

    if MAP[x-1][y]==0 and MAP[x-2][y]==0:
        MAP[x-2][y]=1
        Q.append((x-2,y))
        ANS+=BT[x-2]*BY[y]

    if MAP[x][y+1]==0 and MAP[x][y+2]==0:
        MAP[x][y+2]=1
        Q.append((x,y+2))
        ANS+=BT[x]*BY[y+2]

    if MAP[x][y-1]==0 and MAP[x][y-2]==0:
        MAP[x][y-2]=1
        Q.append((x,y-2))
        ANS+=BT[x]*BY[y-2]


    if ANS>=1<<62:
        print("INF")
        sys.exit()

print(ANS)

Submission status: Runtime Error

Solution code:
#!/usr/bin/env python3

import sys
from queue import Queue
from pprint import pprint
sys.setrecursionlimit(300000)


def solve(N: int, M: int, A: "List[int]", B: "List[int]", C: "List[int]", D: "List[int]", E: "List[int]", F: "List[int]"):
    xs, ys = {}, {}
    xs[0] = 0
    ys[0] = 0
    for i in range(N):
        xs[A[i]] = 0
        xs[B[i]] = 0
        ys[C[i]] = 0
    for i in range(M):
        xs[D[i]] = 0
        ys[E[i]] = 0
        ys[F[i]] = 0

    sx, sy = [], []
    ox = sorted(xs.keys())
    for i, x in enumerate(ox):
        xs[x] = i
        sx.append(x)
    oy = sorted(ys.keys())
    for i, y in enumerate(oy):
        ys[y] = i
        sy.append(y)

    h, w = len(sy) * 2, len(sx) * 2
    g = [[0] * w for _ in range(h)]
    for i in range(N):
        y = ys[C[i]] * 2
        for x in range(xs[A[i]] * 2, xs[B[i]] * 2 + 1):
            g[y][x] = 1
    for i in range(M):
        x = xs[D[i]] * 2
        for y in range(ys[E[i]] * 2, ys[F[i]] * 2 + 1):
            g[y][x] = 1

    x, y = xs[0] * 2, ys[0] * 2
    g[y][x] = 2
    q = Queue()
    q.put((x, y))
    dx = [0, -1, 0, 1]
    dy = [1, 0, -1, 0]
    ret = 0
    #pprint(g)
    while not q.empty():
        x, y = q.get()
        if x % 2 and y % 2:
            xx = sx[x // 2 + 1] - sx[x // 2]
            yy = sy[y // 2 + 1] - sy[y // 2]
            ret += xx * yy
        for k in range(len(dx)):
            tx, ty = x + dx[k], y + dy[k]
            if not (0 <= tx < w and 0 <= ty < h):
                print('INF')
                return
            if g[ty][tx] == 0:
                g[ty][tx] = 2
                q.put((tx, ty))
    #pprint(g)

    #ret = 0
    #for y in range(h):
    #    for x in range(w):
    #        if g[y][x] != 2:
    #            continue
    #        if x == 0 or x == w - 1 or y == 0 or y == h - 1:
    #            print('INF')
    #            return
    #        if x % 2 == 0 or y % 2 == 0:
    #            continue
    #        xx = sx[x // 2 + 1] - sx[x // 2]
    #        yy = sy[y // 2 + 1] - sy[y // 2]
    #        ret += xx * yy
    print(ret)
    return

def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    A = [int()] * (N)  # type: "List[int]"
    B = [int()] * (N)  # type: "List[int]"
    C = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
        C[i] = int(next(tokens))
    D = [int()] * (M)  # type: "List[int]"
    E = [int()] * (M)  # type: "List[int]"
    F = [int()] * (M)  # type: "List[int]"
    for i in range(M):
        D[i] = int(next(tokens))
        E[i] = int(next(tokens))
        F[i] = int(next(tokens))
    solve(N, M, A, B, C, D, E, F)

if __name__ == '__main__':
    main()

Submission status: Runtime Error

Solution code:
#!/usr/bin/env python3

import sys
from pprint import pprint
sys.setrecursionlimit(300000)


def solve(N: int, M: int, A: "List[int]", B: "List[int]", C: "List[int]", D: "List[int]", E: "List[int]", F: "List[int]"):
    xs, ys = {}, {}
    xs[0] = 0
    ys[0] = 0
    for i in range(N):
        xs[A[i]] = 0
        xs[B[i]] = 0
        ys[C[i]] = 0
    for i in range(M):
        xs[D[i]] = 0
        ys[E[i]] = 0
        ys[F[i]] = 0

    sx, sy = [], []
    ox = sorted(xs.keys())
    for i, x in enumerate(ox):
        xs[x] = i
        sx.append(x)
    oy = sorted(ys.keys())
    for i, y in enumerate(oy):
        ys[y] = i
        sy.append(y)

    h, w = len(sy) * 2, len(sx) * 2
    g = [[0] * w for _ in range(h)]
    for i in range(N):
        y = ys[C[i]] * 2
        for x in range(xs[A[i]] * 2, xs[B[i]] * 2 + 1):
            g[y][x] = 1
    for i in range(M):
        x = xs[D[i]] * 2
        for y in range(ys[E[i]] * 2, ys[F[i]] * 2 + 1):
            g[y][x] = 1

    x, y = xs[0] * 2, ys[0] * 2
    g[y][x] = 2
    q = [(x, y)]
    dx = [0, -1, 0, 1]
    dy = [1, 0, -1, 0]
    ret = 0
    #pprint(g)
    while True:
        nex = []
        for x, y in q:
            if x % 2 and y % 2:
                xx = sx[tx // 2 + 1] - sx[tx // 2]
                yy = sy[ty // 2 + 1] - sy[ty // 2]
                ret += xx * yy
            for k in range(len(dx)):
                tx, ty = x + dx[k], y + dy[k]
                if tx <= 0 or tx >= w - 1 or ty <= 0 or ty >= h - 1:
                    print('INF')
                    return
                if g[ty][tx] == 0:
                    g[ty][tx] = 2
                    nex.append((tx, ty))
        if len(nex) == 0:
            break
        q = nex
    #pprint(g)

    #ret = 0
    #for y in range(h):
    #    for x in range(w):
    #        if g[y][x] != 2:
    #            continue
    #        if x == 0 or x == w - 1 or y == 0 or y == h - 1:
    #            print('INF')
    #            return
    #        if x % 2 == 0 or y % 2 == 0:
    #            continue
    #        xx = sx[x // 2 + 1] - sx[x // 2]
    #        yy = sy[y // 2 + 1] - sy[y // 2]
    #        ret += xx * yy
    print(ret)
    return

def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    A = [int()] * (N)  # type: "List[int]"
    B = [int()] * (N)  # type: "List[int]"
    C = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
        C[i] = int(next(tokens))
    D = [int()] * (M)  # type: "List[int]"
    E = [int()] * (M)  # type: "List[int]"
    F = [int()] * (M)  # type: "List[int]"
    for i in range(M):
        D[i] = int(next(tokens))
        E[i] = int(next(tokens))
        F[i] = int(next(tokens))
    solve(N, M, A, B, C, D, E, F)

if __name__ == '__main__':
    main()

Submission status: Runtime Error

Solution code:
import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

def compress(S):
    """ 座標圧縮 """

    zipped, unzipped = {}, {}
    for i, a in enumerate(sorted(S)):
        zipped[a] = i
        unzipped[i] = a
    return zipped, unzipped

def bfs(grid, src):
    """ BFS(グリッド、重みなし) """
    from collections import deque

    H, W = len(grid), len(grid[0])
    directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
    visited = list2d(H, W, 0)
    que = deque()
    for h, w in src:
        que.append((h, w))
        visited[h][w] = 1
    while que:
        h, w = que.popleft()
        for dh, dw in directions:
            h2 = h + dh
            w2 = w + dw
            # 外壁まで行ったら即終了
            if grid[h2][w2] == -1:
                print('INF')
                exit()
            if grid[h2][w2] == 1:
                continue
            if visited[h2][w2]:
                continue
            visited[h2][w2] = 1
            que.append((h2, w2))
    return visited

N, M = MAP()
vert = []
horz = []
S1 = set([0])
S2 = set([0])
for i in range(N):
    h1, h2, w = MAP()
    h1 *= 2
    h2 *= 2
    w *= 2
    vert.append((h1, h2, w))
    S1.add(h1)
    S1.add(h1+1)
    S1.add(h2)
    S1.add(h2+1)
    S2.add(w)
    S2.add(w+1)
for i in range(M):
    h, w1, w2 = MAP()
    h *= 2
    w1 *= 2
    w2 *= 2
    horz.append((h, w1, w2))
    S1.add(h)
    S1.add(h+1)
    S2.add(w1)
    S2.add(w1+1)
    S2.add(w2)
    S2.add(w2+1)

zph, unzph = compress(S1)
zpw, unzpw = compress(S2)
H, W = len(zph), len(zpw)

grid = list2d(H, W, -1)
for i in range(1, H-1):
    for j in range(1, W-1):
        grid[i][j] = 0
for i in range(N):
    h1, h2, w = vert[i]
    w = zpw[w] + 1
    for h in range(zph[h1]+1, zph[h2]+2):
        grid[h][w] = 1
for i in range(M):
    h, w1, w2 = horz[i]
    h = zph[h] + 1
    for w in range(zpw[w1]+1, zpw[w2]+2):
        grid[h][w] = 1

res = bfs(grid, [(zph[0], zpw[0])])
# for row in res:
#     print(row)

ans = 0
sh, sw = zph[0]&1, zpw[0]&1
for i in range(sh, H-1, 2):
    for j in range(sw, W-1, 2):
        if res[i][j]:
            hln = unzph[i+2] - unzph[i]
            wln = unzpw[j+2] - unzpw[j]
            ans += hln * wln
print(ans//4)

Submission status: Runtime Error

Solution code:
import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

def compress(S):
    """ 座標圧縮 """

    zipped, unzipped = {}, {}
    for i, a in enumerate(sorted(S)):
        zipped[a] = i
        unzipped[i] = a
    return zipped, unzipped

def bfs(grid, src):
    """ BFS(グリッド、重みなし) """
    from collections import deque

    H, W = len(grid), len(grid[0])
    directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
    visited = list2d(H, W, 0)
    que = deque()
    for h, w in src:
        que.append((h, w))
        visited[h][w] = 1
    while que:
        h, w = que.popleft()
        for dh, dw in directions:
            h2 = h + dh
            w2 = w + dw
            if grid[h2][w2] == -1:
                print('INF')
                exit()
            if grid[h2][w2] == 1:
                continue
            if visited[h2][w2]:
                continue
            visited[h2][w2] = 1
            que.append((h2, w2))
    return visited

N, M = MAP()
vert = []
horz = []
S1 = set([0])
S2 = set([0])
for i in range(N):
    h1, h2, w = MAP()
    h1 *= 2
    h2 *= 2
    w *= 2
    vert.append((h1, h2, w))
    S1.add(h1)
    # S1.add(h1-1)
    S1.add(h1+1)
    S1.add(h2)
    # S1.add(h2-1)
    S1.add(h2+1)
    S2.add(w)
    # S2.add(w-1)
    S2.add(w+1)
for i in range(M):
    h, w1, w2 = MAP()
    h *= 2
    w1 *= 2
    w2 *= 2
    horz.append((h, w1, w2))
    S1.add(h)
    # S1.add(h-1)
    S1.add(h+1)
    S2.add(w1)
    # S2.add(w1-1)
    S2.add(w1+1)
    S2.add(w2)
    # S2.add(w2-1)
    S2.add(w2+1)

zph, unzph = compress(S1)
zpw, unzpw = compress(S2)
H, W = len(zph), len(zpw)

grid = list2d(H, W, -1)
for i in range(1, H-1):
    for j in range(1, W-1):
        grid[i][j] = 0
for i in range(N):
    h1, h2, w = vert[i]
    w = zpw[w]
    for h in range(zph[h1], zph[h2]+1):
        grid[h][w] = 1
for i in range(M):
    h, w1, w2 = horz[i]
    h = zph[h]
    for w in range(zpw[w1], zpw[w2]+1):
        grid[h][w] = 1

res = bfs(grid, [(zph[0], zpw[0])])
# for row in res:
#     print(row)

ans = 0
sh, sw = 1 - zph[0]&1, 1 - zpw[0]&1
for i in range(sh, H-1, 2):
    for j in range(sw, W-1, 2):
        if res[i][j]:
            hln = unzph[i+2] - unzph[i]
            wln = unzpw[j+2] - unzpw[j]
            ans += hln * wln
print(ans//4)

Submission status: Runtime Error

Solution code:
import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

def compress(S):
    """ 座標圧縮 """

    zipped, unzipped = {}, {}
    for i, a in enumerate(sorted(S)):
        zipped[a] = i
        unzipped[i] = a
    return zipped, unzipped

def bfs(grid, src):
    """ BFS(グリッド、重みなし) """
    from collections import deque

    H, W = len(grid), len(grid[0])
    directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
    visited = list2d(H, W, 0)
    que = deque()
    for h, w in src:
        que.append((h, w))
        visited[h][w] = 1
    while que:
        h, w = que.popleft()
        for dh, dw in directions:
            h2 = h + dh
            w2 = w + dw
            if grid[h2][w2] == -1:
                print('INF')
                exit()
            if grid[h2][w2] == 1:
                continue
            if visited[h2][w2]:
                continue
            visited[h2][w2] = 1
            que.append((h2, w2))
    return visited

N, M = MAP()
vert = []
horz = []
S1 = set([0])
S2 = set([0])
for i in range(N):
    h1, h2, w = MAP()
    h1 *= 2
    h2 *= 2
    w *= 2
    vert.append((h1, h2, w))
    S1.add(h1)
    S1.add(h1-1)
    S1.add(h1+1)
    S1.add(h2)
    S1.add(h2-1)
    S1.add(h2+1)
    S2.add(w)
    S2.add(w-1)
    S2.add(w+1)
for i in range(M):
    h, w1, w2 = MAP()
    h *= 2
    w1 *= 2
    w2 *= 2
    horz.append((h, w1, w2))
    S1.add(h)
    S1.add(h-1)
    S1.add(h+1)
    S2.add(w1)
    S2.add(w1-1)
    S2.add(w1+1)
    S2.add(w2)
    S2.add(w2-1)
    S2.add(w2+1)

zph, unzph = compress(S1)
zpw, unzpw = compress(S2)
H, W = len(zph), len(zpw)

grid = list2d(H, W, -1)
for i in range(1, H-1):
    for j in range(1, W-1):
        grid[i][j] = 0
for i in range(N):
    h1, h2, w = vert[i]
    w = zpw[w]
    for h in range(zph[h1], zph[h2]+1):
        grid[h][w] = 1
for i in range(M):
    h, w1, w2 = horz[i]
    h = zph[h]
    for w in range(zpw[w1], zpw[w2]+1):
        grid[h][w] = 1

res = bfs(grid, [(zph[0], zpw[0])])
# for row in res:
#     print(row)

ans = 0
sh, sw = 1 - zph[0]&1, 1 - zpw[0]&1
for i in range(sh, H-1, 2):
    for j in range(sw, W-1, 2):
        if res[i][j]:
            hln = unzph[i+1] - unzph[i-1]
            wln = unzpw[j+1] - unzpw[j-1]
            ans += hln * wln
print(ans//4)

Submission status: Runtime Error

Solution code:
import sys,bisect,string,math,time,functools,random,fractions
from heapq import heappush,heappop,heapify
from collections import deque,defaultdict,Counter
from itertools import permutations,combinations,groupby
def Golf():*a,=map(int,open(0))
def I():return int(input())
def S_():return input()
def IS():return input().split()
def LS():return [i for i in input().split()]
def LI():return [int(i) for i in input().split()]
def LI_():return [int(i)-1 for i in input().split()]
def NI(n):return [int(input()) for i in range(n)]
def NI_(n):return [int(input())-1 for i in range(n)]
def StoLI():return [ord(i)-97 for i in input()]
def ItoS(n):return chr(n+97)
def LtoS(ls):return ''.join([chr(i+97) for i in ls])
def GI(V,E,ls=None,Directed=False,index=1):
    org_inp=[];g=[[] for i in range(V)]
    FromStdin=True if ls==None else False
    for i in range(E):
        if FromStdin:
            inp=LI()
            org_inp.append(inp)
        else:
            inp=ls[i]
        if len(inp)==2:
            a,b=inp;c=1
        else:
            a,b,c=inp
        if index==1:a-=1;b-=1
        aa=(a,c);bb=(b,c);g[a].append(bb)
        if not Directed:g[b].append(aa)
    return g,org_inp
def GGI(h,w,search=None,replacement_of_found='.',mp_def={'#':1,'.':0},boundary=1):
#h,w,g,sg=GGI(h,w,search=['S','G'],replacement_of_found='.',mp_def={'#':1,'.':0},boundary=1) # sample usage
    mp=[boundary]*(w+2);found={}
    for i in range(h):
        s=input()
        for char in search:
            if char in s:
                found[char]=((i+1)*(w+2)+s.index(char)+1)
                mp_def[char]=mp_def[replacement_of_found]
        mp+=[boundary]+[mp_def[j] for j in s]+[boundary]
    mp+=[boundary]*(w+2)
    return h+2,w+2,mp,found
def TI(n):return GI(n,n-1)
def bit_combination(n,base=2):
    rt=[]
    for tb in range(base**n):s=[tb//(base**bt)%base for bt in range(n)];rt+=[s]
    return rt
def gcd(x,y):
    if y==0:return x
    if x%y==0:return y
    while x%y!=0:x,y=y,x%y
    return y
def show(*inp,end='\n'):
    if show_flg:print(*inp,end=end)
 
YN=['YES','NO'];Yn=['Yes','No']
mo=10**9+7
inf=float('inf')
FourNb=[(-1,0),(1,0),(0,1),(0,-1)];EightNb=[(-1,0),(1,0),(0,1),(0,-1),(1,1),(-1,-1),(1,-1),(-1,1)];compas=dict(zip('WENS',FourNb));cursol=dict(zip('LRUD',FourNb))
l_alp=string.ascii_lowercase
#sys.setrecursionlimit(10**7)
input=lambda: sys.stdin.readline().rstrip()
 
class Tree:
    def __init__(self,inp_size=None,ls=None,init=True,index=0):
        self.LCA_init_stat=False
        self.ETtable=[]
        if init:
            if ls==None:
                self.stdin(inp_size,index=index)
            else:
                self.size=len(ls)+1
                self.edges,_=GI(self.size,self.size-1,ls,index=index)
        return
 
    def stdin(self,inp_size=None,index=1):
        if inp_size==None:
            self.size=int(input())
        else:
            self.size=inp_size
        self.edges,_=GI(self.size,self.size-1,index=index)
        return
    
    def listin(self,ls,index=0):
        self.size=len(ls)+1
        self.edges,_=GI(self.size,self.size-1,ls,index=index)
        return
 
    def __str__(self):
        return  str(self.edges)
 
    def dfs(self,x,func=lambda prv,nx,dist:prv+dist,root_v=0):
        q=deque()
        q.append(x)
        v=[-1]*self.size
        v[x]=root_v
        while q:
            c=q.pop()
            for nb,d in self.edges[c]:
                if v[nb]==-1:
                    q.append(nb)
                    v[nb]=func(v[c],nb,d)
        return v
 
    def EulerTour(self,x):
        q=deque()
        q.append(x)
        self.depth=[None]*self.size
        self.depth[x]=0
        self.ETtable=[]
        self.ETdepth=[]
        self.ETin=[-1]*self.size
        self.ETout=[-1]*self.size
        cnt=0
        while q:
            c=q.pop()
            if c<0:
                ce=~c
            else:
                ce=c
                for nb,d in self.edges[ce]:
                    if self.depth[nb]==None:
                        q.append(~ce)
                        q.append(nb)
                        self.depth[nb]=self.depth[ce]+1
            self.ETtable.append(ce)
            self.ETdepth.append(self.depth[ce])
            if self.ETin[ce]==-1:
                self.ETin[ce]=cnt
            else:
                self.ETout[ce]=cnt
            cnt+=1
        return
    
    def LCA_init(self,root):
        self.EulerTour(root)
        self.st=SparseTable(self.ETdepth,init_func=min,init_idl=inf)
        self.LCA_init_stat=True
        return
    
    def LCA(self,root,x,y):
        if self.LCA_init_stat==False:
            self.LCA_init(root)
        xin,xout=self.ETin[x],self.ETout[x]
        yin,yout=self.ETin[y],self.ETout[y]
        a=min(xin,yin)
        b=max(xout,yout,xin,yin)
        id_of_min_dep_in_et=self.st.query_id(a,b+1)
        return self.ETtable[id_of_min_dep_in_et]
 
class SparseTable: # O(N log N) for init, O(1) for query(l,r)
    def __init__(self,ls,init_func=min,init_idl=float('inf')):
        self.func=init_func
        self.idl=init_idl
        self.size=len(ls)
        self.N0=self.size.bit_length()
        self.table=[ls[:]]
        self.index=[list(range(self.size))]
        self.lg=[0]*(self.size+1)
        
        for i in range(2,self.size+1):
            self.lg[i]=self.lg[i>>1]+1
 
        for i in range(self.N0):
            tmp=[self.func(self.table[i][j],self.table[i][min(j+(1<<i),self.size-1)]) for j in range(self.size)]
            tmp_id=[self.index[i][j] if self.table[i][j]==self.func(self.table[i][j],self.table[i][min(j+(1<<i),self.size-1)]) else self.index[i][min(j+(1<<i),self.size-1)] for j in range(self.size)]
            self.table+=[tmp]
            self.index+=[tmp_id]
    
    # return func of [l,r)
    def query(self,l,r):
        if r>self.size:r=self.size
        #N=(r-l).bit_length()-1
        N=self.lg[r-l]
        return self.func(self.table[N][l],self.table[N][max(0,r-(1<<N))])
    
    # return index of which val[i] = func of v among [l,r)
    def query_id(self,l,r):
        if r>self.size:r=self.size
        #N=(r-l).bit_length()-1
        N=self.lg[r-l]
        a,b=self.index[N][l],self.index[N][max(0,r-(1<<N))]
        if self.table[0][a]==self.func(self.table[N][l],self.table[N][max(0,r-(1<<N))]):
            b=a
        return b
    
    def __str__(self):
        return str(self.table[0])
 
    def print(self):
        for i in self.table:
            print(*i)
 
class Comb:
    def __init__(self,n,mo=10**9+7):
        self.fac=[0]*(n+1)
        self.inv=[1]*(n+1)
        self.fac[0]=1
        self.fact(n)
        for i in range(1,n+1):
            self.fac[i]=i*self.fac[i-1]%mo
            self.inv[n]*=i
            self.inv[n]%=mo
        self.inv[n]=pow(self.inv[n],mo-2,mo)
        for i in range(1,n):
            self.inv[n-i]=self.inv[n-i+1]*(n-i+1)%mo
        return
    
    def fact(self,n):
        return self.fac[n]
        
    def invf(self,n):
        return self.inv[n]
 
    def comb(self,x,y):
        if y<0 or y>x:
            return 0
        return self.fac[x]*self.inv[x-y]*self.inv[y]%mo

def dijkstra(edge,st):
    # edge=[[(v_to,dist_to_v),...],[],...]
    # initialize: def: d=dist(st,i), prev=[previous vertex in minimum path], q[]
    n=len(edge)
    d=[(0 if st==i else inf) for i in range(n)]
    prev=[0]*n
    q=[(j,i) for i,j in enumerate(d)]
    heapify(q)
    v=[False]*n
    # calc
    while q:
        dist,cur=heappop(q)
        if v[cur]:
            continue
        v[cur]=True
        for dst,dist in edge[cur]:
            alt=d[cur]+dist
            if alt<d[dst]:
                d[dst]=alt
                prev[dst]=cur
                heappush(q,(alt,dst))
    return d,prev


show_flg=False
show_flg=True
ans=0
inf=1<<70
n,m=LI()
X=[0,inf,-inf]
Y=[0,inf,-inf]
V=[]
H=[]
for i in range(n):
    a,b,c=LI()
    V.append(((a,b),c))
    Y.append(c)

n+=2
V.append(((-inf,inf),inf))
V.append(((-inf,inf),-inf))

for i in range(m):
    a,b,c=LI()
    H.append((a,(b,c)))
    X.append(a)

m+=2
H.append((inf,(-inf,inf)))
H.append((-inf,(-inf,inf)))


X.sort()
xdc={}
c=1
for j in sorted(set(X)):
    xdc[c]=j
    c+=1
nx=c-1

Y.sort()
ydc={}
c=1
for j in sorted(set(Y)):
    ydc[c]=j
    c+=1
ny=c-1

xdcr=dict(zip(xdc.values(),xdc.keys()))
ydcr=dict(zip(ydc.values(),ydc.keys()))

mp=[[0]*(2*nx+2) for i in range(2*ny+2)]
mpx=[[0]*(2*nx+2) for i in range(2*ny+2)]
#mpy=[[0]*(2*nx+2) for i in range(2*ny+2)]

XX=X+[inf]
for (a,b),c in V:
    a=XX[bisect.bisect(X,a-0.5)]
    b=XX[bisect.bisect_left(X,b)]
    mpx[ydcr[c]*2][xdcr[a]*2]+=1
    mpx[ydcr[c]*2][xdcr[b]*2+1]+=-1
for i in range(0,2*ny+2,2):
    for j in range(2*nx+1):
        mpx[i][j+1]+=mpx[i][j]

YY=Y+[inf]
for d,(e,f) in H:
    e=YY[bisect.bisect(Y,e-0.5)]
    f=YY[bisect.bisect_left(Y,f)]
    
    mp[ydcr[e]*2][xdcr[d]*2]+=1
    mp[ydcr[f]*2+1][xdcr[d]*2]+=-1
for j in range(0,2*nx+2,2):
    for i in range(2*ny+1):
        mp[i+1][j]+=mp[i][j]

for i in range(2*ny+2):
    for j in range(2*nx+2):
        mp[i][j]|=mpx[i][j]



v=[[0]*(2*nx+2) for i in range(2*ny+2)]
q=deque()
q.append((2*xdcr[0]+1,2*ydcr[0]+1))
v[2*ydcr[0]+1][2*xdcr[0]+1]=1
while q:
    cx,cy=q.popleft()
    px,py=cx>>1,cy>>1
    
    ans+=(xdc[px]-xdc[px+1])*(ydc[py]-ydc[py+1])
    #show((cx,cy),(xdc[px]-xdc[px-1])*(ydc[py]-ydc[py-1]),(xdc[px],xdc[px-1]),(ydc[py],ydc[py-1]))
    #show((cx,cy),px,py)
    for dx,dy in FourNb:
        nbx=cx+dx*2
        nby=cy+dy*2
        if (not 0<=nbx<2*nx+2) or (not 0<=nby<2*ny+2) or v[nby][nbx]==1:
            continue
        
        if mp[nby-dy][nbx-dx]==0:
            q.append((nbx,nby))
            v[nby][nbx]=1

if ans>=inf:
    ans='INF'
print(ans)