2020年5月18日月曜日

第一回日本最強プログラマー学生選手権予選 C - Cell Inversion

区間の組み合わせの総数が求まれば、操作の順番の総数はN!N!を掛けて得られるので、前者を求めればよい。

SSを左から走査して、閉じていない区間を保持しながらDPすることを考える。つまり、

dp[x][y]:=x\operatorname{dp}[x][y] := x文字目までみて、閉じていない区間がyy個あるような場合の数

というDPをする。xx文字目がWWyyが偶数、もしくはxx文字目がBByyが奇数なら、ここでyy個の(閉じていない)区間のどれかを閉じるのが正しいので、

dp[x+1][y1]+=ydp[x][y] \operatorname{dp}[x+1][y-1] \operatorname{+=} y \cdot \operatorname{dp}[x][y]

xx文字目がBByyが偶数、もしくはxx文字目がWWyyが奇数なら、さらに新しい区間を開始して反転を1増やすべきなので

dp[x+1][y+1]+=dp[x][y] \operatorname{dp}[x+1][y+1] \operatorname{+=} \operatorname{dp}[x][y]

このDPはO(N2){O}(N^2)の形になっているが、実際にやってみると各xxについて有効なyyは高々1つしかないことがわかるので、線形で書ける。


コンテスト当時にはまったくわからなくて、解説を読んでも天才解法に見えた問題だった。今見ると、いわゆる箱根駅伝DPを書けばアドホックな考察をしなくても解けてしまうことがわかる。

ただ、O(N2){O}(N^2)のDPが見えているときに、それの延長として想定解が導ける場合とかなり難しい場合があって、コンテスト中にそちらにどこまで頭を使うかは微妙なところとは思う。今出ても、ムーブ次第ではまりかねない気がする。