ARC129

3完。悔しい。

A - Smaller XOR

Nで立ってるビットと同じ位置がxでも立っていれば小さくできるが、それより上のビットでNで立ってなくてxで立ってるということが起こると大きくなってしまう。わからないので桁DPした。少し前に書いた記事からコピペしてくる。書いててよかった~と思ったけど桁DP要らないらしいですね。

(追記)あー桁DPで下から考える癖が付いていた。上から考えれば、Nの立ってるビットそれぞれについて、そこが1でそこより上が全部0のxは全て小さくなる。重複もないので足していくだけ。ただ条件を満たす個数を具体的に求める実装はけっこう難しい。n未満のものを求めるとして、clamp(n - m, 0LL, m) ときれいに書けたけど、だいぶ時間がかかった。考察も含めると脳死桁DPとどっちが早いかは微妙。

B - Range Point Distance

かなり難しそうな見た目。つい和で考えてしまうけど最大値なんだよなあ(わかっていても思考がそっちへ行く)(AをAにしては高度な典型で解いたのでBもまさかCHTか、などといった考えがちらつく)。真ん中へんに置くのがよさそうではある。けっこう考えたけど、実はわりと簡単で、一番左にある右端と一番右にある左端のちょうど中間に置けばいい。その2つの区間だけ見たとき、それより改善しようがないし、他の区間は影響しない。間がないときは全部の区間の中に入れるので0。

C - Multiple of 7

長さ10^6以下でNと同じだからそれ使うのかなとか思いながら考える。7は自明な7の倍数なんだから、7を並べれば三角数が作れると気づく。そういえばNは高々3つの三角数の和で表せるんだよな。7771777のように7以外の数字で区切ったらどうなる?1を含む区間をとれば、7717のようになり7707は明らかに7の倍数で10(10の冪)は7の倍数でないから、7の倍数にならずに済んでいる!1が2つ入るケースが心配だが、7以外の数字を2つ含んで7の倍数になる場合、どんな取り方をしても7の倍数になる。だから、1だけずらしてやれば(717717であれば727717とすれば)7の倍数にならなくなる。あとは3個以下の三角数への具体的な分割。O(N)を目指して考える。2個への分割を列挙するのもあるのかな。実際には二重ループで、内側はしゃくとりでやった。典型と考察のバランスがよくて好き。

(追記)貪欲でいいんかい。調べたら、26795のとき6個に分割されて最大だった(けっこう多くなるんだな)。解説の累積和を求めるみたいなやつは、シンプルで言われれば実装できるもののかなり高度に感じた。累積和がわかってからの復元もかなり難しい。強い人にとっては楽なのだろう。次元の違いを感じる。

D - -1+2-1

逆の操作(+1 -2 +1)はできるのかと考えて、実験を手計算ではなくプログラムを書いて行うことでこの問題のコードを書く練習になってよいと思いそうした。言われてみれば当たり前だが自分以外に1周操作すれば逆の操作をしたことになる(自分も含め全部操作すれば元通り)。しかしかなり回数がかかる。隣との差が0になるよう貪欲に合わせていくような方針がないか考えたが、ある場所の差が変化する操作は4つもあり、元の3つから増えている。ここで、差をとる逆の累積和を思いつく。累積和をとれば操作で変化する場所が2つに減った!しかし意外とはっきりしない。もう1回累積和をとる勇気もない。ループしてるのが相当厄介。累積和のN-1個の値の和を考えて、とりあえずこれを0にすることは必要なので0にしてみる。累積和の総和を変える操作はA[0]とA[N-1]の境界をまたぐ操作2つ。この2つを1回ずつ行うと、両端を-1と+1することになり他の操作とあわせて対称性がよくなる。こうなればもう1回累積和だ。この累積和も最終的には全て0になる必要がある。操作で累積和がどう変わるか観察すると、N-2個の範囲で好きな場所で-1するか全部に+1するか(これはコスト2)。よって、最も小さいものが負ならそれを埋めるように+1する必要があり、その後-1で全部0にすればいい。総和は変化しないのでそれが0でなかったらダメ。

残り2分くらいで書き上がったが、サンプルが通らないどころかREを起こしている様子。終了後に調べると、累積和を取るとき1個余計に回してて範囲外アクセスしてた。また、総和を合わせる操作で符号を間違えていた。さらに、コスト2の処理をしていなかった。これでようやくサンプルが合い、提出してWA。つらい。レーティングは上がったのにこんな気持ちになることがあると思い出した。

(追記)AC取った。上に書いた符号を間違えていたところで、足す位置が符号によって違うのをコードに反映させ忘れていた。昨日はできていた「頑張って1箇所も間違えないように書いていく」ができなかった。Cまでけっこう速く解けて緊張感がなかったところへ難しそうなDということで、心拍数が上がってきたのは最後の最後。今日はコンテストが始まってからは体調もよかったし、立ち回りも特に悪くなかったと思うが、ここまでズタボロにコーディングのミスをしてしまうというのは本当に難しい。これでミスをなくそうとガチガチになったらこんな難しい問題サンプルを試すところまでも行かないし、単に実力不足なんだけど、この4個のミスがなければ通っていたと思うとやはり悔しい。