人間だけど競プロやる

解けなかった問題を理解できたら記事を投稿します。日本語の解説が見つからなかったもの中心。

Codeforces Round #668 (Div. 2) C. Balanced Bitstring

Codeforces Round #668 (Div. 2) C. Balanced Bitstring


気づき

  1. インデックス mod K で一致する
  2. 範囲内で片方が\frac{K}{2}より多く存在したら不適


1.について
問題を眺めていても閃かないので、この手の問題の常套手段をまず確認する。

  1. 具体的に手を動かす
  2. 抽象的に手を動かす
  3. 前から操作する
  4. 後ろから操作する
  5. 操作しても変わらない箇所(単位元)を探す
  6. 2回操作すると、もとに戻る操作(逆元)を探す


他にもあるだろうけど、まずはこれだけ確認しておく。


この問題については、「1」「2」「5(の亜種)」がヒントとなる。
1.はサンプルなどを具体的に操作して問題を理解するだけなので、スルー。

f:id:bqn2:20200907232934p:plain
fig.1

2.、5.について、fig.1のように考えると、
与えられる文字列をSSi文字目をS_i、範囲の長さをKとして、
S_iS_{i+K}は等しくなければならないとわかる。
よって、任意のi,jについて、S_{i\%K} = S_{j\%K}が要求される。
ここでこの気付きを、5.(の亜種)としたのは、範囲を一つずらしたとき、長さK-2の共通部分があり、その範囲内の0と1の数は変わらないので、共通部分の左右は同じ値になる、という、変化しない共通部分を見つけていることに対応する。


これらの事実より、S_{i\%K} = S_{j\%K}が成り立たない場合、その時点で不適。
また、S_{i\%K} = S_{j\%K}が成り立たないといけないので、\mod Kが等しいインデックスの中に「?」と「1または0」が存在すると、?01どちらかに決定する。
これらの操作をすると、S_{i\%K} = S_{j\%K}が常に成り立つ状態になるので、始点0からK-1に対して、含まれる0の数が\frac{K}{2}より大きくないかチェックすればOK。
\because 0\frac{K}{2}より多い場合、含まれる?をすべて1にしても不適だから)
始点0からK-1だけチェックすれば大丈夫なのは、具体的にコードを書いてみるとわかるが、a=vec[vec[;K]]という配列をとって、
a[i%K].push(S[i])
と追加して、?を決定する操作をすると、任意i,jについてa_i=a_jとなるので、a_0の範囲で始点を試せば、あとは同じチェックになる。