ABC224

ABCFGの5完。1700点は6人だった。Dで破滅したが、どうにか最低限のパフォは確保できた。

A - Tires

s.substr(s.size() - 2) == "er"。istのほうでやろうとするとSが3文字あるとは限らないのでダメ。けっこう難しかったと思うが、そこそこスピードを出せてよかった。

(追記)最後の文字だけ見ればいいの気がつかなかった。まあコンテスト中の動きとしてはよかったけど。

B - Mongeness

問題文を読むのがかなり大変。四重ループで解くことになるのだが、やはりそこまでネストが深くなると人間にとって根本的に難しいのだろう。条件に出てくる変数が4つなので4乗で間に合うことが確認できればそれでよい(2500の2乗は間に合うなという競プロ的思考をした)。条件に面白い意味がなさそうなので(ほんとはあるのかもしれないけど自分にはわからなかったので)、その部分の実装がけっこう大変(意味がわかっていれば空で書けるが、今回は問題文を見ながら書き写した)。

(追記)問題名見てなかった。そうなのかー。解説もちゃんと見てなかった。

C - Triangle?

制約が全探索。3点が一直線上にないこととたぶん同値。まあ外積で(そもそも外積で三角形の面積求まるし)。考察はやや怪しいし時間もかかったが、実装は瞬殺だった。

D - 8 Puzzle on Graph

9の階乗が36万で辺も高々8本/頂点なのでグラフで殴ってOK。まずnext_permutationで列挙しに行ったが、頂点番号は配列ではなく数、8^9(9^8が正しい気がする、これならありか)は無理なので配列の双方向変換も必要、普通に実装すると二重ループになって脳の負荷が高い、「頂点iに何があるか」「コマjがどこにあるか」という2種類の表現があり迷うし混乱する。

時間だけが過ぎていく。簡単だと思っているのに手が動かないので、何もできない。落ち着いて考え直そうとも思ったが、既に脳が何も感じないのっぺらぼうになっている。unratedのときは、前半は順番に撃破していくことが多いのだが、簡単だと思った問題でここまで時間を消費することがあるとなると、考え直す必要がある(コンテスト中という集中して楽しく考えられる時間がさすがにもったいない)。「コマjがどこにあるか」という方針に切り替えて半分実装してからスワップが面倒なことに気づいて心が折れ、Dだけでコンテスト時間が終わることが想像できたため、21:43に離脱。

(追記)双方向の変換は必要なかった。何を混乱していたのか思い出せない。楽な解法としては、9^9が10^9より小さくintに収まるので順列を数値に変換してそれをunordered_mapで[0, 9!)に対応させる。あるいはarrayをそのままmapに突っ込んでも間に合う。TLが4秒であることに気づいてなかった(今回は気づいてもあまり関係なかったが、余裕がないときにこうなるので気をつけたい(願望))。

E - Integers on Grid

setでvector持って突っ込んで辺を張るのがまず見える(HやWは小さいからset要らなかった、D問題で頭がかなり疲れている)。列(行を想像してたなあ)でやったら同じことを行でもやればいい。同じ列にたくさんあったらソートして必要な辺だけ張るようにしないといけない。実装する。ソート対象で混乱する(位置はあまり関係なくて書かれている整数が重要)。コードを書いて考えが整理されたところで、同じ列に2と3がN/2こずつあるようなケースで死ぬことに気づく。グラフを具体的に構築したら間に合わない。まとめることはできるかもしれないが、位置が違えば状況も異なるので難しそう。逆に考えても(小さいほうへ移動すると考えても)同じだよな?とか思って、同じだから都合がいいのかそれとも意味がないのか混乱した(今考えるとスタート地点がある側とそうでない側という非対称が一応ある)。わからないのでFへ(途中でFGを覗いて簡単そうな気配を感じたというのもある)(時刻は21:58)。

(追記)わからないので解説を見た。トポロジカルソートしたいとは思っていたんよ。DPできるから。しかしグラフの辺の数が2乗になるから困っていた。具体的に辺を張る必要はなく、単にaでソートすればいいだけだった。aが同じ区間で区切るのが面倒だが、解説ではmap内のvectorにaで振り分けて突っ込んでた。

F - Problem where +s Separate Digits

まず、半分に切ってそこに+を入れる場合を考えてみる。四角い図を描いて少し考えると、総和への左側の寄与は、左の通り数と右の総和の積。素直にやると2乗になりそうな気もするが行けそうなのでこの方針にする。通り数は2冪で簡単なので、総和を端から求めていけばよさそう。が、実装していくと間違いに気づく。1個ずつ継ぎ足していくためには、+を入れない場合も考える必要がある(今考えると、元の方針で素直にやると最後の+の位置毎に計算するなどして2乗かかる)。そこで、最後の数の総和も持つことにする。空間計算量O(1)でもできそう。1文字足すときに、+を入れるかどうかで場合分けして、入れないときは最後の数の総和を10倍してS_iを足す感じで。最初だけ+なし固定なので、ループは|S|-1回に。

G - Roll or Increment

残り26分くらいだが、その時間で通せる見た目をしている。これサイコロにする必要あった?最初出てる目を書き直すのかと思ったよ。少し考えると、操作Aをしてから操作Bをする意味はない。操作Bを何回かやって操作Aを何回かやってゴールという展開だけ考えればよい。操作Bで失敗したら何も残らないのだが、ここで少し混乱した(「だから何」みたいな)。操作Aしかできないとしたときの期待値は簡単。次に操作Bでどこへ降り立つかという話になる。落ち着いて考えると、各点に期待値が定まっておりそれが操作Aだけの期待値より小さければ操作Bでやり直すべき。つまり、なんだか都合がいいようだが、ある範囲に入るまで操作Bを繰り返すのが最適。範囲を全探索はできないが、Tから下に数えていくつかに注目して、その範囲を1以上x以下としたときの期待値はxで表せる。式を見ると三分探索できそう(今考えるとどう証明するかわからんな)だが、前回できなかった1/xの微分を今回はやってみることにした。まあ簡単ではある。微分して0になるところと両端を見ればよい。一応前後1000を見る。サンプルが通らず、-1000から1000までも見ると通るので提出して自信はなかったがAC。あとで気づいたけど両端見てないじゃん。

(追記)やはり片方の端しか見ていなかったせいで嘘だった。

H - Security Camera 2

(追記)何もわからないけど解説の方法でACだけ取った。