Buggy python submission (verdict: Time Limit Exceeded):
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()

# 高速化のため事前ソート

# A.sort(reverse=True)結局使わなかった
# B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = True if x in A else False
    flgB = True if x in B else False
    # print(flgA, flgB)
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))


Fixed submission:
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()

# 高速化のため事前ソート

A.sort(reverse=True)
B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = False
    flgB = False
    for a in A[n_A:]:
        if a == x:
            flgA = True
            break
    for a in B[n_B:]:
        if a == x:
            flgB = True
            break
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))

Buggy python submission (verdict: Time Limit Exceeded):
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()

# 高速化のため事前ソート

A.sort(reverse=True)
B.sort(reverse=True)


def ret_n_given_x(x):
    flgA = True if x in A else False
    flgB = True if x in B else False
    # print(flgA, flgB)
    if flgA and flgB:
        return 1
    elif flgA:
        ret = 0
        for b in B:
            if x <= b:
                ret += 1
            else:
                break
        return ret
    elif flgB:
        ret = 0
        for a in A:
            if x <= a:
                ret += 1
            else:
                break
        return ret
    else:
        retb = 0
        for b in B:
            if x <= b:
                retb += 1
            else:
                break
        reta = 0
        for a in A:
            if x <= a:
                reta += 1
            else:
                break
        return (retb * reta)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))


Fixed submission:
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()

# 高速化のため事前ソート

A.sort(reverse=True)
B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = False
    flgB = False
    for a in A[n_A:]:
        if a == x:
            flgA = True
            break
    for a in B[n_B:]:
        if a == x:
            flgB = True
            break
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))

Buggy python submission (verdict: Time Limit Exceeded):
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()


def ret_n_given_x(x):
    flgA = True if x in A else False
    flgB = True if x in B else False
  #  print(flgA, flgB)
    if flgA and flgB:
        return 1
    elif flgA:
        ret = 0
        for b in B:
            if x <= b:
                ret += 1
        return ret
    elif flgB:
        ret = 0
        for a in A:
            if x <= a:
                ret += 1
        return ret
    else:
        retb = 0
        for b in B:
            if x <= b:
                retb += 1
        reta = 0
        for a in A:
            if x <= a:
                reta += 1
        return (retb * reta)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
#    print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))


Fixed submission:
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print(0)
    exit()
if len(set(B)) != len(B):
    print(0)
    exit()

# 高速化のため事前ソート

A.sort(reverse=True)
B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = False
    flgB = False
    for a in A[n_A:]:
        if a == x:
            flgA = True
            break
    for a in B[n_B:]:
        if a == x:
            flgB = True
            break
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print(int(ans))