解法
良い文字列である必要十分条件が, 悪い箇所が一つもないこと. つまり,悪い箇所の存在を高速に判定できれば良い. 変化した部分が少ないので,そこだけ更新.
答えるクエリでは,0,1が交互に並んでいるか (\in Bool) を判定する. 区間を反転するクエリでは,区間の内部は交互に並んでいるか (\in Bool) は変わらない. Bool に入っているか変化するのは,区間の両端だけ. i番目と i+1番目が同じか \(\in Bool\) を set に入れておく. \([l,r)\) に対して,set に入っているかを判定する.
実装
0-indexed, [l,r) で考える. \(v[i] \in Bool\) を,\(v[i] = true\) iff \(s[i] = s[i+1]\) とする. ただし,\(i = 0, N\) は使わない. \(s[l,r)\) が良いか判定するとき,調べるべきは\(v[{[l+1,r-1]}]\) の中に true が存在しないことを調べれば十分. これは,set の lower bound, upper bound で求まる.
\(l+1 \leq r-1\) とする.
の一番左の \([\) が lower bound(l+1), 一番右の \()\) が upper bound(r-1).
注意
\(r = l+1\) のとき,区間 \([l+1, r-1]\) は空になるので, 個別に判定.この場合は長さ 1の文字列なので,良い文字列になる.
使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"