loj6074

题意

loj

做法

这里字符集为([0,9))
(f_{i,j})为前(i)个字符,以(j)结尾的本质不同个数,显然

[egin{cases} f_{i,j}=f_{i-1,j}&j eq c_i\ f_{i,c_i}=sumlimits_{j}f_{i-1,j}+1 end{cases} ]

我们将其写成(10 imes 10)矩阵的形式,格外将长度(+1)来保存常数(1)
(M_i)表示字符为(i)的转移矩阵,其在单位矩阵的基础上,第(i)列全为(1)

[egin{aligned} M_i = egin{pmatrix}1 & & 1 & & \ & 1 & 1 & & \ & & 1 & & \ & & vdots & ddots & \ & & 1 & & 1 end{pmatrix} \end{aligned}]

对于([l,r])的询问,答案为

[egin{pmatrix}0&0 & 0 & cdots & 0 & 1end{pmatrix}prodlimits_{i=l}^r M_{s_i}egin{pmatrix}1 \ 1 \ 1 \ vdots \ 1 end{pmatrix} ]

(I_1=egin{pmatrix}0&0 & 0 & cdots & 0 & 1end{pmatrix})(I_2=egin{pmatrix}1&1 & 1 & cdots & 1end{pmatrix}^T)

我们将其拆分成两部分来维护:
(I_1cdot M_{s_{l-1}}^{-1}M_{s_{l-2}}^{-1}cdots M_{s_1}^{-1})
(M_{s_1}M_{s_2}cdots M_{s_r}cdot I_2)

我们对于所有的(iin[0,n]),预处理出上面的两部分
(A_1=I_1M_{s_{i-1}}^{-1}M_{s_{i-2}}^{-1}cdots M_{s_1}^{-1})
(A_2=M_{s_1}M_{s_2}cdots M_{s_i}cdot I_2)

[egin{aligned} M_i^{-1} = egin{pmatrix}1 & & -1 & & \ & 1 & -1 & & \ & & -1 & & \ & & vdots & ddots & \ & & -1 & & 1 end{pmatrix} \end{aligned}]

对于第一部分
由于(I_1)仅有第(9)行有效
那么我们其实没必要将整个({A_1})存下来,仅需知道每个矩阵最后一行即可

当我们(A)左乘上(M_c^{-1}),观察会发生什么变化
(i)列整体减去(A_{c,i})(i eq c)
(c)列不发生变化
我们对矩阵(A)维护一个矩阵(A'),且每一列维护(tag_i),表示(A_{i,j}=A'_{i,j}+tag_j)
假设当前某一列为(egin{pmatrix}a_0+tag_i,a_1+tag_i,cdots,a_c+tag_i,cdots,a_{9}+tag_iend{pmatrix}^T)
那么其将变成:(egin{pmatrix}a_0-a_c,a_1-a_c,cdots,a_c+tag_i,cdots,a_{9}-a_cend{pmatrix}^T)
(a_c+tag_i)改写成((2a_c+tag_i)-a_c)
那么我们仅需对(A)每一行的((i,c))位置,以及({tag_i})修改,即可维护出最后一行

对于第二部分
最后会将矩阵乘上(I_2),这个的意义是每一行之和
那么我们其实没必要将整个({A_2})存下来,仅需知道每个矩阵的列向量(A')(A'_i)(A_i)(i)行之和)

当我们(A)右乘上(M_c),观察会发生什么变化
对于(A_{i,c}(iin[0,9])),其修改为第(i)行之和;其他位置不变
那么每次(A)一行中只会有一个位置发生变化
我们在维护(A)的同时很容易预处理出列向量(A')

时间复杂度(O(10(n+q)))

code

可能上面讲的有点绕,可以看下代码
code

原文地址:https://www.cnblogs.com/Grice/p/14193815.html