AtCoder Beginner Contest 246 Ex問題メモ

Ex - 01? Queries

問題

  • '0','1','?' の3種の文字のみからなる長さ $N$ の文字列 $S$ が与えられる
  • $Q$ 個のクエリを順番に処理せよ
  • クエリ
    • $x_i,c_i$ が与えられる
    • $S$ の $x_i$ 文字目を $c_i$('0','1','?' のいずれか)に書き換える
      • この変更は以降のクエリにも反映される
    • 「$S$ に含まれる全ての '?' を '0' または '1' に独立に置き換えて得られる文字列の、(連続とは限らない)部分列」としてあり得る文字列の個数を $\mod{998244353}$ で出力する
  • $1 \le N,Q \le 10^5$
  • 実行時間制限: 6sec.

解法

DPの遷移が、小さな行列の積で表現できることを利用して、行列を乗せたセグメント木で必要な箇所だけを更新する。

公式Editorialでは3×3の行列を用いていた。その方が自然なので、基本的にそちらを参照すればよい。

4×4の行列を使って解いたので、考えだけメモ。

  • $DP[i][j]=S$ の先頭 $i$ 文字で作れる部分列で、($j:$ 後述の分類)に属するものの個数

$j$ は、以下の4つの状態の分類とする。

  • oo: 後ろに'0'を置いても'1'を置いても、先頭 $i$ 文字からは作れない部分列となる
  • ox: 後ろに'0'を置いたら新しい部分列となるが、'1'を置いた部分列は先頭 $i$ 文字からも作れる
  • xo: 後ろに'1'を置いたら新しい部分列となるが、'0'を置いた部分列は先頭 $i$ 文字からも作れる
  • xx: 後ろに'0'を置いても'1'を置いても、先頭 $i$ 文字から既に作れる部分列となる

それぞれの状態から、$S$ の $i+1$ 文字目が '0','1','?' のそれぞれの場合だったときに、 「それを末尾に採用したとき(採用したら新しい文字列となる場合のみ)」「採用しなかったとき」で、遷移先が一意に定まる。

   0                1                ?                    遷移先
   oo ox xo xx      oo ox xo xx      oo ox xo xx          ------→
oo [1, 0, 1, 0],    [1, 1, 0, 0],    [2, 0, 0, 1],    遷|
ox [1, 0, 0, 1],    [0, 1, 0, 0],    [1, 0, 0, 1],    移|
xo [0, 0, 1, 0],    [1, 0, 0, 1],    [1, 0, 0, 1],    元|
xx [0, 0, 0, 1],    [0, 0, 0, 1],    [0, 0, 0, 1],      ↓

大まかには、「先頭 $i$ 文字から作れる部分列の集合」を $B_i$ として、

  • $S_{i+1}$ を末尾に採用して新規部分列としたら、その後ろに何かをさらにくっつけた部分列は $B_{i+1}$ には含まれないので、ooに遷移できる(遷移元の状態問わず)
    • たとえば $B_i$ に '00' が含まれ、$S_{i+1}=1$ を追加して新規部分列 '001' が作れるとなったとき、$B_{i+1}$ に '0010' や '0011' が既に含まれる、という状態なら、$B_i$ の時点で '001' が既に含まれていないとおかしいので矛盾
  • $S_{i+1}$ を採用できるのに採用しなかったら、採用したものも $B_{i+1}$ に含まれるので、次からは採用できなくなる
    • $S_{i+1}=0$ のとき、oo なら xo に遷移、ox なら xx に遷移、など

あとは $S$ の各文字に対応する行列を先頭からかけ算していった結果で、1行目の和が答えとなる(初期状態の空文字列は oo にあたるので)。
ただし結果には空文字列も含まれるため、最後に -1 する。

セグメント木の実装に注意。行列積は左項と右項の順番で答えが変わるので、ここを蔑ろにした実装では正しい答えが求まらない。

行列積の計算量はサイズの3乗で利いてくるので、$3^3=27$ と $4^3=64$ では2倍以上効率が悪いが、Pythonでもギリギリで通った。

Python3

programming_algorithm/contest_history/atcoder/2022/0402_abc246.txt · 最終更新: 2022/04/07 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0