AtCoder Beginner Contest #119

published: ,
last modified: .

lang: ja

category: competitive_programming

tags: atcoder ocaml

A. Still TBD

0埋めされた数をきちんとscanfで読めるか不安だったのだがどうやらできるらしい. 解答例

また文字列の辞書順比較でもよかったらしい.

B. Digital Gifts

換算して合計する. 解答例

C. Synthetic Kadomatsu

正答率が低い問題.300点とはいえ私の苦手な操作の特性を考える系の問題が解けたのは大きいと思っている. 解答例

まずN8N \le 8に注目して何らかの全列挙を考えるが,すべての操作について全列挙するのは流石に間に合わなそう.ここで延長/短縮魔法は合成魔法の後に使っても同じであることに注目すると,合成結果を全列挙してから延長/短縮を行えばよいことが分かる.全列挙の計算量はNNが小さいので問題ない.

これにより合成結果が列挙できたから,これに延長/短縮魔法を適用してA,B,Cの候補を選べばよい.これは順序を入れ替えて,A,B,Cの候補を選んでからA,B,Cに揃うように魔法をかければよい.候補をうまく選ぶ方法は割と考えにくそうだが,実はこれも全列挙で間に合う:3重ループでA,B,Cの候補を適当に選んで差を計算すればよい.

別解(editorial)

竹の用法は「Aに使う,Bに使う,Cに使う,使わない」の4通り.よってこの4N4^N通りを試行すればよい.合成回数について:使わなかった竹の本数をssとおくと,nsn-s本の竹が合成によって3本になる.一回の合成で竹が1本減ることから合成の回数はns3n-s-3回となる. 解答例

D. Lazy Faith

最近のABC-Dにしては簡単.最初のACコード(綺麗なものは下掲): 解答例

si,tis_i, t_iをそれぞれ配列S,TS,Tに入れておく.すると各xix_iに対してS,TS,Tを二分探索すれば,左右についてxxに最も近い値sl,sr,tl,trs_l,s_r,t_l,t_rが得られる.存在しない場合が面倒で,変な関数を作ってしまった.もうちょっと簡潔に書けたとは思うが.

移動の方法は次の8つ:

  • tlslx(if tl<sl)t_l \leftarrow s_l \leftarrow x (\text{if } t_l \lt s_l)
  • sltlx(if sl<tl)s_l \leftarrow t_l \leftarrow x (\text{if } s_l \lt t_l)
  • xsrtr(if sr<tr)x \rightarrow s_r \rightarrow t_r (\text{if } s_r \lt t_r)
  • xtrsr(if tr<sr)x \rightarrow t_r \rightarrow s_r (\text{if } t_r \lt s_r)
  • slx,sltrs_l \leftarrow x, s_l \rightarrow t_r(折り返す)
  • tlx,tlsrt_l \leftarrow x, t_l \rightarrow s_r
  • xsr,tlsrx \rightarrow s_r, t_l \leftarrow s_r
  • xtr,sltrx \rightarrow t_r, s_l \leftarrow t_r

これはまずxstx \rightarrow s \rightarrow t(直進)とxs,tsx \rightarrow s, t \leftarrow s(折り返し)を考え,左右反転版を考え,最後に訪れる順番がxtsx \to t \to sとなるものを考えることで列挙した.このうち上4つは次のように纏められる(下4つも纏めると却って複雑になるため行わない):

  • min{tl,sl}x\min \{t_l, s_l\} \leftarrow x
  • xmax{tr,sr}x \rightarrow \max \{t_r, s_r\}

これらのコストを愚直に計算して最小値を取ればよい.コスト計算を1箇所凡ミスして1WA.

editorialでは配列の先頭と末尾に-infとinfを加えている.こうすると二分探索で現れるindexが必ず配列の範囲内になるから取り扱いが楽になる.これは覚えておきたい.このテクニックを用いたコード: 解答例

なお私の解法では1クエリに対して4回二分探索を行ってsl,sr,tl,trs_l,s_r,t_l,t_rを求めているのだが,editorialでは「l=r1*_l = *_{r-1}」という性質を利用して2回に抑えている.確かにr* _rr>x* _r \gt xを満たす最小の候補であるからr1* _{r-1}xx未満であり,これはl<x* _l \lt xを満たす最大の候補(本問ではxxと等しくなるようなi* _ iは存在しない).