以下の操作を 0 回以上 N 回以下行うことができます」という制約が付いていた。一応ね、実装前にざっと制約を探しはしていた。でも制約セクションには入力の制約は書いてあっても出力の制約は書かれていなかったのだな。転倒数の総和の最大値はたぶん入力となる数列が逆順にソートされている場合で、0 から 2N-1 の範囲の和(=N(2N-1))になるから、入力次第で操作回数が N を超える。■次に考えたのは、入力の先頭を出力の先頭にとりあえず配置して、次に配置する要素を、出力の末尾との比較によって入力の前の方から貪欲に引っぱってくる方法。考えなければいけないのは、出力の末尾より大きい(小さい)要素が入力の中に残っていないときにどうやってジグザグを維持するか。たとえば出力の末尾2要素が O1,O2 で入力の残りが I1,I2,I3 のときに大小関係が O1<O2<I1<I2<I3 だったら、O2 より小さい要素を入力から選んでジグザグを作ることができない。解決するのは簡単で、入力の先頭を出力の末尾の1つ手前に挿入すればジグザグになる。O1 との大小関係も大丈夫。I1 が O1 より小さいせいでジグザグが壊れるならそもそも苦労していない。この解法のネックも操作回数で、2N の入力のそれぞれに対して 0 回から複数回の操作が必要になる。ランダム入力では N=100000 に対して 180000 回くらいの操作が必要になった。■次に思いついたのは(考えたって書くのやめちゃった)、さっきの解法の例で出した O1,O2,I1,I2,I3 の中で、O2,I1,I2 の大小関係にだけ注目してジグザグが作れるんじゃないかということ。3つの大小関係がどうであれ0回か1回のスワップで山ないしは谷が作れる。(O2 がスワップ対象だけど)スワップによる既成出力への影響はどうか。スワップが必要なのは真ん中の要素が山なら極大値、谷なら極小値になっていなければいけないのにそうではなかったときだから、山を作るためにスワップされたどちらかの端の要素はそれまでより小さくなり、逆に谷を作るためのスワップでは端の要素が大きくなる。山になる要素の隣は谷になるべき要素だから、スワップで小さくなってもジグザグは維持される。谷を作る場合も同じ。■提出 #34071956 (AC / 331 Byte / 212 ms)。N 回のループの各回で1回以下のスワップだから交換回数も大丈夫。精進だからこそトントントンと AC までステップが踏めたんだろうなあ。2番目のトンがなければ AC につながる3歩目のトンはなかったし、次の一歩が出てこないことも2歩目があさっての方向に向いていることもよくあることなので、5割以上の確率で0完になる AGC はリスキーすぎる。緑だったときにレート変動対象から外れて以来不参加だよ。■■■B 問題「Adjacent Chmax」は小さい P から順番に DP かなと思ったけど、何を記録するのかが(実装を始めても)はっきりせず。
低血糖症(ハイパーグリセミア hyperglycemia)」と書かれていた。低なのに hyper? hypo では? と疑問に思って検索したらやっぱり Wikipedia には hypoglycemia と書いてある。そうだと思った。■ここからが自分の鈍いところだけど、タイポグリセミアに残っているのはグリセミアであって低~要素が残ってないし、高血糖症からできあがっていていけない理由はないよねって思ったけど(食い違っている症状名カタカナ英語のどれが間違いで訂正すべき対象なのかを考えていた)、ややあって typo と hypo がかかっていることに気がついたのだった。hypoglycemia だから typoglycemia なのであって低血糖症でなければいけないのだった。
A.*B
型の入力はどうやっても不可。次に、文字数が奇数のときは中心に自由に使える文字があるので、左右どちらの半分の文字列に対しても右から寄せるような操作も左から寄せるような操作も好きに選ぶことができるので、左右ともに好きな文字列に書き換えられて回文にもできる。ここまでは当日にもわかっていた。今日お風呂で考えていて気がついたのは、ある程度の文字数があればどんな入力でも BA+B+A+B
型か AB+A+B+A
型の文字列に書き換えられるな、ということ。要するに最低5文字あって A.*B
型でなければ常に Yes。というわけであとは N=2 と N=4 だけケアできれば良い。■提出 #33772876 (AC / 258 Byte / 86 ms)。ほとんどどんな文字列でも回文に書き換えられるので、入力の長さと4文字だけ見れば答えが出せる。なんだよそれー。縛りがざる過ぎて逆に手掛かりが少ないのが難しい。■@2022-08-10 それどころではなかったな。こちらの提出 #33643866 (AC / 75 Byte) を見ると A.*B
型と N=2 だけケアすれば答えが出せたらしい。■■■精進2。同 ARC-B「AB Game」(茶 diff)。公倍数を使うのかなとか予想しながら考えてみたらもっと単純だった。まず N/A、N/B でそれぞれが可能な操作回数の最大がわかる。この時点で N/A = 0 なら Alice の負けが確定する。それぞれ最大の回数が決まっていて、自分の操作回数を残しながら相手の操作回数を削るには……とか考え始めたんだけど、もし A<=B なら Alice が最大限取り去った残りは B より少ないのが決まっていて Bob は1回も操作できない。これは逆も言えて、もし A>=B で Bob に操作が回ったなら Alice に勝ちの目はない。0手1手2手までで全部決まる。■提出 #33773060 (AC / 149 Byte / 59 ms)。A の剰余(0..A-1)が A..N のあいだに何周といくつあるかを N/A と N%A で数えるだけ。~だけって言うなら当日に AC を取りなさいよ。d1.values_at(*vs).sum
が vs.sum{|v| d1[v] }
だともっとオーバーする。頂点ごとにまとめた辺(E
)の代わりに辺の集合(UV
)をそのまま使うと制限時間を数倍オーバーする。色々な積み重ねの上できわっきわの AC なんだ。初期値&
で初期値が1のビットに対応する累積結果を取り出し、~初期値&
で初期値が0のビットに対応する累積結果を取り出すみたい。実際、初期値2種類、出力2種類の4通りしか考えることがない単純な問題なんだよ、本来は。自分の提出 #33472932がなんで実際のビット演算をする代わりに :nop, :zero, :one, :flip という疑似演算子を使っているかというと、初期値のビットが1の場合と0の場合の2種類のケースを分けて準備すればいいということに気がつけなかったから、0が来ても1が来ても1つのデータで両対応できるように、疑似演算子を操作して実際の演算を遅延させるしかなかった。疑似演算子だから 30 ビット並列でまとめて計算することもできなかった。不思議だね、愚か者は自分で問題を難しくするんだね。そして本当に難しい問題は自分が理解できる程度まで過度に単純化して間違えるんだよね。度し難い。