ARC161

4完。いやなんつーきついセットだ。Aが難しすぎるし、CDは実装が時間かかるし、そもそもB以外みんな証明できないし。

同レート帯と比べて実装力がないのを感じる。この俺が!?

A - Make M

最初に、Aのある要素より小さい要素が過半数ある必要があるって考えたけど進展せず。あとになって、小さいのばっかでもダメなことに気づいた。何もわからない。一旦飛ばしてBへ。

もうしょうがないので、順位表を見てペナが少ないのを確認してそれっぽいのを提出してAC。

自分が考えていた(考えたかった)イメージは、解説にある「基準値の頻度」だった。これが多いとどうしても隣り合ってしまうから不可能になる。いや難しすぎる。300点で出していい証明難度じゃない。

B - Exactly Three Bits

popcountで場合分けできそうだが、実装がかなり重くなるのでもう少し考える(1はいいとして2がけっこう厄介)。まず、条件を満たす最小の整数が7なので、7以上かで場合分け。popcountが3未満なら3以上になるまでデクリメントする(当時は変に場合分けして考えてたけど下3桁を見れば8回はかからない)。次に、popcountが3になるまで立ってる最下位ビットを消す(n &= n - 1;)。上の3つだけ残すより大きいものとなると、最上位を上に動かすか、最上位をそのままにして2番目を動かすか、上の2つをそのままに3番目を動かすかになるが、いずれも元の数より大きくなってしまう。なのでOK。

C - Dyed by Majority (Odd Tree)

葉とその隣は決まるが、他が理詰めで決まるのかそれとも他の方法があるのか、わからない。二部グラフなので問題を分割できるが、やはりわからない。Dと交互に考えていた。とりあえず、多数決で決めてそれが正しいか確認して出力という処理を書いてみる。サンプルは通るが、なんか答えが複数ありうるのに対称な解法で気持ち悪いし、反例がないか考えてみると普通に反例がある(これ短時間で見つけたのはえらい)。

葉(脳内ではリーフと呼んでいる)は決まるし、決まったやつらしか隣にいないやつも実質葉だろうと思い、なんとかDFSでできないかと画策する。DFSしてから周囲の情報を集めて実質葉を判定するようなやばいコードを書いていたが、時間もなくなってきて、ここで一旦落ち着こう。そのコードを捨てて、きれいにまた書き始めた。葉を特別扱いするのをやめ、DFS的なコードにする。親に対してこの色でなくては困る(子だけで過半数を確保できていない)という場合はその色を返す。子がそう言ってきたらその色にするし、そうでなければ親の色にする。三項演算子を使う余裕すらなかったが、なんかACした。

D - Everywhere is Sparser than Whole (Construction)

辺がどこかに固まってると、そこを抜き取られたときに困る。ばらけさせればよさそう。そもそも、「密度」に関する条件関係なく構成するのがけっこう難しい(と思ってたけど単にダブらないよう追加してくだけだな)。ということで、対称性のある構成をすればそれで通りそうな、そういう都合のいい雰囲気がある。D=1は全体で閉路を作ればいいから簡単で、そうでないときは頂点番号を1ずつずらすのではなく2とか3とかでやれば同様の閉路が追加されそう。ここで、N=10, D=6のとき多重辺ができてしまうのと、N=10, D=5のとき長さ2の閉路は認められないのと、そういうのがまずいと思っていたが、そもそもそういうのは完全グラフよりも辺が多いので自明にNoだとあとになって気づいた。N=10だとD=4.5(?)が境目になるんだけど、都合の悪いところをきれいに回避していて、これが正解だろうなという思いが強まる。

実装だが、ステップ幅がNと互いに素ならきれいな閉路になるし、そうじゃなくてもいくつか閉路ができて問題ないと考えていた。なので閉路毎に出力していたが、まあ言われてみれば閉路を意識することなく単に各頂点からステップ幅だけ先の頂点へ辺を張るだけでよかった。こういうところで力の差が出るんだよな。なんか最初に、N=10, D=4で頂点1から4本辺を出したら頂点1へ後ろから辺が入ってきて増えちゃうみたいに思ってたけど目指すのは次数8だしそれでいい。問題の難しさに圧されて簡単なこともできなくなる。