ABC346

5完。Fが通せずゴミのような気分に。

A - Adjacent Product

これ1分切ったのはえらい。

B - Piano

blockquoteになってる部分を読んで損した。

無限というのは難しい。条件を満たす部分文字列はW+B文字になる。2乗が間に合うので、開始地点を全探索すればいい。サンプルが通って見直しをしたら、開始地点をW+B通り試すようになっていて、"wbwbwwbwbwbw"の長さ通りに直した。あぶねー(2乗って何の2乗だよ)。12通り試せば、全部の状況をカバーできる。s[(i + j) % n] == 'w' みたいにしてwをカウントして12通りのうち一つでもWと一致すればYes。かなりの総合力がないと苦戦しそうな問題。

C - Σ

ちょっと待って今気づいたけど10^9じゃなくて2*10^9なの。最初2*10^5に空目してたのはそのせいかあ。気づいてからも、10^9だと思って解いていた。そっか、10^9だと愚直が通ってしまうのか。

2*10^5だと思って迷走していたけど、10^9となれば覚悟が決まる。Aをsortしてuniqueして、1からKまでの整数の和から引いていく。K以下のやつのみ引くのだと書き始めてから気づいて危ない。これで本当に正しいという証明もできない。いや、証明はできるけどその証明が正しいという実感を得る方法がわからないという感じか。

D - Gomamayo Sequence

手で例を作って観察すると、同じ2文字が2連続になる場所がどこかN-1通りとその同じ文字が0か1かの2通りで良い文字列は2*(N-1)通りだとわかる。少し考えると、左右からやるいつものになる。これもう飽きた。

DPでもできるらしいです。初期値の設定が面倒。遷移も難しくはない普通のDPだが、自分は実装するまで形が見えなかった。

問題名見てなかったけどゴママヨじゃん!

E - Paint

操作を逆から見るやつ。最初から全部色0になってるのは、逆から見て最後に全部色0で塗ればいい。今気づいたけど、色0で縦横両方塗り潰してたけど横だけでいい。行を塗るときは、その行を塗ったことがあれば何もしない、初めてなら、幅Wから列を塗った回数を引いたぶんだけその色が増える。塗ったかどうかと回数を管理するのだが、長さ2の配列で縦横まとめてやるべきだったかなあ。シンプルに書ける確信がなくてベタ書きしてしまった。なんで全部の色について出力させないんだろう。

F - SSttrriinngg in StringString

かなりいかつい見た目で苦労するが、問題の意味がわかってしまえば、二分探索で貪欲に部分列をとっていくだけ。各文字について文字数の累積和を前計算しておく。答えが0になるケース(Tの文字でSに含まれないものがある場合)は先に判定しておく。Sが長くてTが短いとき答えはNよりだいぶ大きくなることがあるので、二分探索の上限は10^18とかにしておく。あとは、何個目のSの何文字目まで使ったか管理しながら、割り算と累積和の二分探索で進めていく。

サンプルが全部0だったのは、a[h][i + 1] = a[h][i] + (s[i] == 'a' + h); の括弧が抜けていたからだった。直しても微妙に合わないのは、割り算であまりが0のとき、例えばSの3個分の文字を使うとき必ず3個分進むようになっていて実はその文字があるところだけ使えばいいから3個分丸々は進まなくていいというやつだった。サンプルが合って提出してWA。Sが3個と1文字というときSは4個使うのに3個としていた。あとからちゃんと詰めようと思っていたところを忘れている。負荷が高いので仕方ないというかいちいちメモするしかないのかな。直して提出してまたWA。10^18を何回も足したらオーバーフローするのでNを超えたらさっさとfalseを返すようにする。またWA。ていうかWAが提出のたびに減っているとはいえ大量にあり何か根本的に間違っていそう。結局わからないままコンテストが終わった。解説のコードを追加して手元で適当なテストケースを作り自分のコードと出力が異なるものを見つける(すぐに見つかった)。確かに間違っているので、どこでおかしくなっているか変数の中身を出力させながら絞り込んでいくと、a[h][l] - a[h][i] と2回書いてその2回の間にiを変更していた。2回書く(コピペする)ときに、変数に入れようかと検討はしたが余裕がなくてそのままにしてしまった。

G - Alone

Gまで読んで順位表を見て、しばらくFG交互に考えていたが、Gはわからず、Fが素直にできると気づいてFに専念。

(追記)3週間以上経ってしまったが、AC。まず、解説にあったLibrary Checkerの問題をやる。こちらは座標圧縮が必要。区間の最小値と最小値の個数を持って区間加算という、どうやって思いつくか全くわからないものを考えると確かに解けている。遅延セグ木の実装もわりと簡単だ。要素数を1増やしてそこに0個の0を入れておくことで常に全体の最小値を0にできる。元の問題に戻ると、LとしてありえるN通りを横に、RとしてありえるN通り(こちらは何通りでもいい)を縦にとって、条件を満たす(L, R)についてそれらが交わるマスを塗って、塗られたマスの面積を求める問題にする。A_iの値毎に位置を記録していくつかの長方形を追加して面積を求めればよい。