AtCoder diverta 2019 Programming Contest 2 C - Successive Subtraction
irisruneです。他言語に慣れているとpythonの変数名にキャメルケースを使おうとするたびに警告を出されるのはもやもやします。
B問題より簡単という噂を聞きましたが全然そんなことはなかったです。見た目以上に考えることが多く、ACするのに5回かかりました。
import sys import collections as col import bisect import numpy as np def main(): n = int(input()) aarray = [int(e) for e in input().split()] aarray.sort() record = [] endpoint = max(1, bisect.bisect(aarray, 0)) aqueue = col.deque(aarray) while len(aqueue) > endpoint + 1: amax = aqueue.pop() amin = aqueue.popleft() record.append((amin, amax)) aqueue.appendleft(amin - amax) amax = aqueue.pop() while len(aqueue) > 0: amin = aqueue.popleft() record.append((amax, amin)) amax -= amin print(amax) for r in record: print(r[0], r[1]) main()
という性質に気付くかどうかが3割くらいだと思います。アルゴリズムが組めるかが4割くらい、コーナーケースの考慮と実装が3割くらいじゃないでしょうか。
上記の性質を使うことで、となるように操作を行えば解くことができます。…と言いたいところですが、すべてのについてとなる場合を考える必要があります。なぜかといえば、となるが最低1つは必要となるためです。
また、逆にすべてのについてとなる場合についても考える必要があります。こちらについても、となるが必要となるためです。
以上より、具体的なアルゴリズムは以下のようになります。
- を昇順にソートする。
- となるを探索する(線形探索でも二分探索でも可)。
- とおいて操作を行い、その結果をに代入することを繰り返す。
- とおいて操作を行い、その結果をに代入することを繰り返す。
- が答えとなる。
…とここまで書いていて気が付いたのですが、単にとなるようにおけばよいだけでした。無駄に複雑な処理を行っていましたね。
ちなみに実装についてはの両方を繰り返し用いるためdequeを使うとスマートに実装できると思います。
雑記
- D問題も見た感じは解けるかと思いましたが、こちらも見た目よりかなり考えることが多く自力ACは難しそうです。