题目描述
给定一个长度为$n$的$01$序列,支持两种操作
- $\forall i \in [l,r] \cap Z,s_i \leftarrow 1 - s_i$
- 查询$s[l \dots r]$中本质不同的子序列个数
题解
先想想如何求一个$01$序列中的本质不同的子序列的个数
设$f_{i,j}$表示$s[1 \dots i]$中,结尾为$j$的本质不同的子序列的个数,其中$i \in [l,r] \cap Z \wedge j \in \\{ 0,1 \\}$
那么有以下转移方程
$$
\begin{cases}
\begin{cases}
f_{i,0} = f_{i-1,0}+f_{i-1,1} + 1 \\
f_{i,1}=f_{i-1,1}
\end{cases}
& \qquad s_i=0 \\
\begin{cases}
f_{i,0}=f_{i-1,0} \\
f_{i,1}=f_{i-1,0}+f_{i-1,1}+1
\end{cases}
& \qquad s_i=1
\end{cases}
$$
转移的含义?
以$s_i=0$为例:新增加一个子序列,以及之前的所有不同的子序列的末尾都增加一个$0$
写成矩阵转移形式
$$
\begin{cases}
\begin{pmatrix}
f_{i,0} & f_{i,1} & 1
\end{pmatrix}
\begin{pmatrix}
1 & 0 & 0 \\
1 & 1 & 0 \\
1 & 0 & 1
\end{pmatrix}
\begin{pmatrix}
f_{i+1,0} & f_{i+1,1} & 1
\end{pmatrix}
& s_i=0 \\
\begin{pmatrix}
f_{i,0} & f_{i,1} & 1
\end{pmatrix}
\begin{pmatrix}
1 & 1 & 0 \\
0 & 1 & 0 \\
0 & 1 & 1
\end{pmatrix}
\begin{pmatrix}
f_{i+1,0} & f_{i+1,1} & 1
\end{pmatrix}
& s_i=1
\end{cases}
$$
这两个转移矩阵可以相互转换的:第一行和第二行交换,然后第一列和第二列交换
之后可以通过线段树维护矩阵,并且打上反转标记实现区间反转的操作(证明略,可以大力展开矩阵乘法来证明)
区间查询的话就是维护矩阵的乘积
代码
1 |
|