cf750e-solution
CF750E Solution
先想想对于只有一个询问怎么做。
考虑 dp,设 \(dp_{i,j}\) 表示前 \(i\) 个字符中,已经找到且仅找到 2017 的前 \(j\) 个字符,同时没有出现 2016,至少需要删掉多少个字符。
初始化:\(dp_{0,0}\gets0\)
转移:
\[dp_{i,0}\gets\begin{cases}dp_{i-1,0}+1&,s_i=2\\dp_{i-1,0}&,s_i\not=2\end{cases}
\]
\[dp_{i,1}\gets\begin{cases}dp_{i-1,1}+1&,s_i=0\\\min(dp_{i-1,0},dp_{i-1,1})&,s_i=2\\dp_{i-1,1}&,\text{otherwise}\end{cases}
\]
\[dp_{i,2}\gets\begin{cases}dp_{i-1,2}+1&,s_i=1\\\min(dp_{i-1,1},dp_{i-1,2})&,s_i=0\\dp_{i-1,2}&,\text{otherwise}\end{cases}
\]
\[dp_{i,3}\gets\begin{cases}dp_{i-1,3}+1&,s_i=6,7\\\min(dp_{i-1,2},dp_{i-1,3})&,s_i=1\\dp_{i-1,3}&,\text{otherwise}\end{cases}
\]
\[dp_{i,4}\gets\begin{cases}dp_{i-1,4}+1&,s_i=6\\\min(dp_{i-1,3},dp_{i-1,4})&,s_i=7\\dp_{i-1,4}&,\text{otherwise}\end{cases}
\]
我们发现所有转移都只和 \(dp_{i-1}\) 有关。
这让我们产生了一个想法,把 \(dp_i\) 储存成一个 \(5\) 行的列向量,通过矩阵乘法进行转移。
但是转移式里面的 \(\min\) 好像和矩乘没什么关系。那么我们试试看定义广义矩阵乘法
\[(A*B)_{i,j}=\min_k(A_{i,k}+B_{k,j})
\]
这玩意看起来是有结合律的。证明:
\[\begin{aligned}
((A*B)*C)_{i,j}&=\min_k((A*B)_{i,k}+C_{k,j})\\
&=\min_k(\min_l(A_{i,l}+B_{l,k})+C_{k,j})\\
&=\min_k\min_l(A_{i,l}+B_{l,k}+C_{k,j})\\
&=\min_l\min_k(A_{i,l}+B_{l,k}+C_{k,j})\\
&=\min_l(\min_k(B_{l,k}+C_{k,j})+A_{i,l})\\
&=\min_l((B*C)_{l,j}+A_{i,l})\\
&=(A*(B*C))_{i,j}\quad\blacksquare
\end{aligned}\]
那么接下来就好办了。对于每一位的字符我们都能根据转移式找到对应的转移矩阵,
于是将所有转移矩阵乘起来再乘上初始状态的矩阵
\[\begin{bmatrix}0\\\infty\\\infty\\\infty\\\infty\\\end{bmatrix}
\]
最后得到的矩阵就是 \(dp_n\),输出第五行的数即可。
至于区间查询,我们只需要用线段树维护这些转移矩阵的乘积,每次查询区间矩阵乘积即可。
复杂度 \(\mathcal O(n+q\log n)\)。

浙公网安备 33010602011771号