C - Manga Editorial by kyopro_friends


この問題は答えを二分探索することで解くことができます。

判定問題「少なくとも \(X\) 巻までを全て読むことができるか?」を考えます。このとき、\(X\) 巻までの本は \(1\) 冊残し、それ以外の本は全て売るとして良いです。残った本+(売った本/2)が \(X\) 以上なら答えはYesになります。

残す本の冊数を求めるには、setの積集合を使うと簡単です。

実装例(Python)

N=int(input())
A=set(map(int,input().split()))

l=0
r=N+1
while r-l>1:
  m=(l+r)//2
  # m巻まで読めるか?
  c=len(set(range(1,m+1))&A)
  if c+(N-c)//2>=m: l=m
  else: r=m

print(l)

この実装例のアルゴリズムの計算量は O(N(log N)^2) であり、十分高速に動作します。

2022/10/03 追記:
CPythonでは set は hash table により実装されているため、 9行目の実行時間は expected \(O(m)\)、 worst \(O(mN)\) となり、このアルゴリズム全体の計算量は expected \(O(N\log N)\)、worst \(O(N^2)\) となります。
https://wiki.python.org/moin/TimeComplexity
Pythonの公式ドキュメントでは計算量に関する規定は見つけられませんでした。ご存知の方は教えてください。
https://docs.python.org/ja/3/library/stdtypes.html#set
また、C++で同様の実装を行う場合、set(range(1,m+1)) に相当するものは \(O(m)\) 時間ででき 、積集合を求めることは 今回のケースでは \(O(m)\) でできるため、アルゴリズム全体の計算量は \(O(N\log N)\) となります。

posted:
last update: