この問題は、適切に集合を管理し、集合演算を計算することができれば解くことができます。集合を扱うには集合型を用いると良いです。例えば Python では、集合型は set
として実装されています。
この問題の難しい点として、集合が直接入力で与えられないことが挙げられます。与えられた を集合に変換せずに解こうとすると、主に実装の面で大変になると思います。
このように、与えられたデータを扱いやすいように整形してから処理するというのは、競技プログラミングに限らず重要な技術ですので、是非身につけましょう。
set
の各メソッドや、各集合演算については、ググってください。
以下は Python の実装例です。
xxxxxxxxxx
N, M = map(int, input().split())
ss = []
for i in range(N):
s = input()
ss.append(s)
# 部員と研究会への所属を扱いやすくするため、belong_to[i] = 部員iの所属している研究会の集合として管理する。
# 空の集合を N 個もつリストを作る。
belong_to = []
for i in range(N):
belong_to.append(set())
for i in range(N):
for j in range(M):
# 部員 i が研究会 j に所属しているなら
if ss[i][j] == "1":
belong_to[i].add(j)
Q = int(input())
# 順にクエリを処理する。
for _ in range(Q):
query = list(map(int, input().split()))
if query[0] == 1:
p = query[1]
# 0-indexに変換
p -= 1
print(len(belong_to[p]))
elif query[0] == 2:
c = query[1]
# 0-indexに変換
c -= 1
# 研究会 c に所属している部員をカウントするための変数
cnt = 0
for i in range(N):
# 部員 i が研究会 c に所属しているなら
if c in belong_to[i]:
cnt += 1
print(cnt)
elif query[0] == 3:
p, c = query[1:]
# 0-indexに変換
p -= 1
c -= 1
# 部員 p の所属している研究会に c を追加
belong_to[p].add(c)
elif query[0] == 4:
p, c = query[1:]
# 0-indexに変換
p -= 1
c -= 1
# 部員 p の所属している研究会から c を削除
belong_to[p].remove(c)
elif query[0] == 5:
p, q = query[1:]
# 0-indexに変換
p -= 1
q -= 1
# 部員 p,q の双方が所属している研究会の数、即ち所属している研究会の積集合の要素数を出力する。
print(len(belong_to[p] & belong_to[q]))
elif query[0] == 6:
p, q = query[1:]
# 0-indexに変換
p -= 1
q -= 1
# 部員 p,q の少なくとも片方が所属している研究会の数、即ち所属している研究会の和集合の要素数を出力する。
print(len(belong_to[p] | belong_to[q]))
elif query[0] == 7:
p, q = query[1:]
# 0-indexに変換
p -= 1
q -= 1
# 部員 p,q の片方のみが所属している研究会の数、即ち所属している研究会の対称差集合の要素数を出力する。
print(len(belong_to[p] ^ belong_to[q]))
elif query[0] == 8:
p, q = query[1:]
# 0-indexに変換
p -= 1
q -= 1
# 部員 p が所属していて、部員 q が所属していない研究会の数、即ち所属している研究会の差集合の要素数を出力する。
print(len(belong_to[p] - belong_to[q]))