Official

C - Participants 3 Editorial by Forested


さまざまな解法が考えられます。

\(\Theta(NM)\) 時間の解法

列挙する数は必ず \(B\) に現れます。よって、 \(B\) の数全てについて \(A\) に現れるかどうかを判定することで列挙ができます。一回の判定に \(\Theta(N)\) 時間かけると、全体の計算量は \(\Theta(NM)\) 時間になります。

n, m = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

ans = [x for x in b if a.count(x) == 0]
print(len(ans))
for num in ans:
    print(num)

\(\Theta((N + M) \log N)\) 時間の解法

上の解法ではある数が \(A\) に含まれるかどうかの判定に一回あたり \(\Theta(N)\) 時間かけていました。 \(A\) をあらかじめソートしておくと二分探索が適用でき、一回の判定が \(\Theta(\log N)\) 時間になります。ソートに \(\Theta(N \log N)\) 時間かけると、全体の計算量は \(\Theta((N + M) \log N)\) になります。

# a に x が含まれるかを二分探索で判定
def binary_search(a, x):
    low, high = -1, len(a)
    while high - low > 1:
        mid = (high + low) // 2
        if a[mid] >= x:
            high = mid
        else:
            low = mid
    return high != len(a) and a[high] == x

n, m = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

a.sort()

ans = [x for x in b if not binary_search(a, x)]
print(len(ans))
for num in ans:
    print(num)

\(\Theta(\mathrm{MAX})\) 時間の解法

\(\mathrm{MAX}\)\(A\)\(B\) に含まれる数の最大値とします。ある数 \(x\)\(A\) の中に現れるかと \(B\) の中に現れるかはそれぞれ長さ \(\mathrm{MAX} + 1\) の配列で管理できます。時間計算量は \(\Theta(\mathrm{MAX})\) です。

n, m = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

MAX = 3000

a_count = [False] * (MAX + 1)
for x in a:
    a_count[x] = True
b_count = [False] * (MAX + 1)
for x in b:
    b_count[x] = True

ans = [x for x in range(MAX + 1) if not a_count[x] and b_count[x]]
print(len(ans))
for num in ans:
    print(num)

補足

\(A\)\(B\) を集合とみなすと、この問題で計算したいものは差集合 \(B \setminus A\) です。差集合を求める関数や演算子が用意されている言語では、それを使うと自分で実装する必要がなく、簡単にこの問題を解くことができます。

n, m = map(int, input().split())
a = set(map(int, input().split()))
b = set(map(int, input().split()))

ans = b - a
print(len(ans))
for num in ans:
    print(num)

posted:
last update: