题目
CF750E New Year and Old Subsequence
分析
设
d
p
[
i
]
[
0
/
1
/
2
/
3
/
4
]
dp[i][0/1/2/3/4]
dp[i][0/1/2/3/4] 表示前
i
i
i 个数字只能依次匹配到
ϕ
/
{
2
}
/
{
2
,
0
}
/
{
2
,
0
,
1
}
/
{
2
,
0
,
1
,
7
}
\phi/\{2\}/\{2, 0\}/\{2, 0, 1\}/\{2, 0, 1, 7\}
ϕ/{2}/{2,0}/{2,0,1}/{2,0,1,7} 的最小删除代价,则
d
p
[
i
]
[
0
]
=
{
d
p
[
i
−
1
]
[
0
]
s
i
≠
2
d
p
[
i
−
1
]
[
0
]
+
1
s
i
=
2
d
p
[
i
]
[
1
]
=
{
d
p
[
i
−
1
]
[
1
]
s
i
∉
{
2
,
0
}
d
p
[
i
−
1
]
[
1
]
+
1
s
i
=
0
min
{
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
}
s
i
=
2
d
p
[
i
]
[
2
]
=
{
d
p
[
i
−
1
]
[
2
]
s
i
∉
{
0
,
1
}
d
p
[
i
−
1
]
[
2
]
+
1
s
i
=
1
min
{
d
p
[
i
−
1
]
[
1
]
,
d
p
[
i
−
1
]
[
2
]
}
s
i
=
0
d
p
[
i
]
[
3
]
=
{
d
p
[
i
−
1
]
[
3
]
s
i
∉
{
1
,
7
,
6
}
d
p
[
i
−
1
]
[
3
]
+
1
s
i
∈
{
7
,
6
}
min
{
d
p
[
i
−
1
]
[
2
]
,
d
p
[
i
−
1
]
[
3
]
}
s
i
=
1
d
p
[
i
]
[
4
]
=
{
d
p
[
i
−
1
]
[
4
]
s
i
∉
{
7
,
6
}
d
p
[
i
−
1
]
[
4
]
+
1
s
i
=
6
min
{
d
p
[
i
−
1
]
[
3
]
,
d
p
[
i
−
1
]
[
4
]
}
s
i
=
7
\begin{aligned} dp[i][0] &= \begin{cases} dp[i - 1][0] & s_i \neq 2\\ dp[i - 1][0] + 1 & s_i = 2 \end{cases} \\ dp[i][1] &= \begin{cases} dp[i - 1][1] & s_i \notin \{2, 0\} \\ dp[i - 1][1] + 1 & s_i = 0 \\ \min\{dp[i - 1][0], dp[i - 1][1]\} & s_i = 2 \\ \end{cases} \\ dp[i][2] &= \begin{cases} dp[i - 1][2] & s_i \notin \{0, 1\} \\ dp[i - 1][2] + 1 & s_i = 1 \\ \min\{dp[i - 1][1], dp[i - 1][2]\} & s_i = 0 \\ \end{cases} \\ dp[i][3] &= \begin{cases} dp[i - 1][3] & s_i \notin \{1, 7, 6\} \\ dp[i - 1][3] + 1 & s_i \in \{7, 6\} \\ \min\{dp[i - 1][2], dp[i - 1][3]\} & s_i = 1 \\ \end{cases} \\ dp[i][4] &= \begin{cases} dp[i - 1][4] & s_i \notin \{7, 6\} \\ dp[i - 1][4] + 1 & s_i = 6 \\ \min\{dp[i - 1][3], dp[i - 1][4]\} & s_i = 7 \end{cases} \end{aligned}
dp[i][0]dp[i][1]dp[i][2]dp[i][3]dp[i][4]={dp[i−1][0]dp[i−1][0]+1si=2si=2=⎩⎪⎨⎪⎧dp[i−1][1]dp[i−1][1]+1min{dp[i−1][0],dp[i−1][1]}si∈/{2,0}si=0si=2=⎩⎪⎨⎪⎧dp[i−1][2]dp[i−1][2]+1min{dp[i−1][1],dp[i−1][2]}si∈/{0,1}si=1si=0=⎩⎪⎨⎪⎧dp[i−1][3]dp[i−1][3]+1min{dp[i−1][2],dp[i−1][3]}si∈/{1,7,6}si∈{7,6}si=1=⎩⎪⎨⎪⎧dp[i−1][4]dp[i−1][4]+1min{dp[i−1][3],dp[i−1][4]}si∈/{7,6}si=6si=7 构造转移矩阵
M
i
M_i
Mi 使得
M
i
×
(
d
p
[
i
−
1
]
[
0
]
d
p
[
i
−
1
]
[
1
]
d
p
[
i
−
1
]
[
2
]
d
p
[
i
−
1
]
[
3
]
d
p
[
i
−
1
]
[
4
]
)
=
(
d
p
[
i
]
[
0
]
d
p
[
i
]
[
1
]
d
p
[
i
]
[
2
]
d
p
[
i
]
[
3
]
d
p
[
i
]
[
4
]
)
M_i \times \begin{pmatrix} dp[i - 1][0] \\ dp[i - 1][1] \\ dp[i - 1][2] \\ dp[i - 1][3] \\ dp[i - 1][4] \\ \end{pmatrix} = \begin{pmatrix} dp[i][0] \\ dp[i][1] \\ dp[i][2] \\ dp[i][3] \\ dp[i][4] \\ \end{pmatrix}
Mi×⎝⎜⎜⎜⎜⎛dp[i−1][0]dp[i−1][1]dp[i−1][2]dp[i−1][3]dp[i−1][4]⎠⎟⎟⎟⎟⎞=⎝⎜⎜⎜⎜⎛dp[i][0]dp[i][1]dp[i][2]dp[i][3]dp[i][4]⎠⎟⎟⎟⎟⎞ 其中矩阵乘法定义改变
+
→
min
,
×
→
+
+ \to \min, \times \to +
+→min,×→+。
不难发现
M
i
=
{
(
1
+
∞
+
∞
+
∞
+
∞
0
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
)
s
i
=
2
(
0
+
∞
+
∞
+
∞
+
∞
+
∞
1
+
∞
+
∞
+
∞
+
∞
0
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
)
s
i
=
0
(
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
1
+
∞
+
∞
+
∞
+
∞
0
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
)
s
i
=
1
(
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
1
+
∞
+
∞
+
∞
+
∞
0
0
)
s
i
=
7
(
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
1
+
∞
+
∞
+
∞
+
∞
+
∞
1
)
s
i
=
6
(
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
+
∞
+
∞
+
∞
+
∞
+
∞
0
)
s
i
∉
{
2
,
0
,
1
,
7
,
6
}
M_i = \begin{cases} \begin{pmatrix} 1 & +\infty & +\infty & +\infty & +\infty \\ 0 & 0 & +\infty & +\infty & +\infty \\ +\infty & +\infty & 0 & +\infty & +\infty \\ +\infty & +\infty & +\infty & 0 & +\infty \\ +\infty & +\infty & +\infty & +\infty & 0 \\ \end{pmatrix} & s_i = 2 \\ \\ \begin{pmatrix} 0 & +\infty & +\infty & +\infty & +\infty \\ +\infty & 1 & +\infty & +\infty & +\infty \\ +\infty & 0 & 0 & +\infty & +\infty \\ +\infty & +\infty & +\infty & 0 & +\infty \\ +\infty & +\infty & +\infty & +\infty & 0 \\ \end{pmatrix} & s_i = 0 \\ \\ \begin{pmatrix} 0 & +\infty & +\infty & +\infty & +\infty \\ +\infty & 0 & +\infty & +\infty & +\infty \\ +\infty & +\infty & 1 & +\infty & +\infty \\ +\infty & +\infty & 0 & 0 & +\infty \\ +\infty & +\infty & +\infty & +\infty & 0 \\ \end{pmatrix} & s_i = 1 \\ \\ \begin{pmatrix} 0 & +\infty & +\infty & +\infty & +\infty \\ +\infty & 0 & +\infty & +\infty & +\infty \\ +\infty & +\infty & 0 & +\infty & +\infty \\ +\infty & +\infty & +\infty & 1 & +\infty \\ +\infty & +\infty & +\infty & 0 & 0 \\ \end{pmatrix} & s_i = 7 \\ \\ \begin{pmatrix} 0 & +\infty & +\infty & +\infty & +\infty \\ +\infty & 0 & +\infty & +\infty & +\infty \\ +\infty & +\infty & 0 & +\infty & +\infty \\ +\infty & +\infty & +\infty & 1 & +\infty \\ +\infty & +\infty & +\infty & +\infty & 1 \\ \end{pmatrix} & s_i = 6 \\ \\ \begin{pmatrix} 0 & +\infty & +\infty & +\infty & +\infty \\ +\infty & 0 & +\infty & +\infty & +\infty \\ +\infty & +\infty & 0 & +\infty & +\infty \\ +\infty & +\infty & +\infty & 0 & +\infty \\ +\infty & +\infty & +\infty & +\infty & 0 \\ \end{pmatrix} & s_i \notin \{2, 0, 1, 7, 6\} \end{cases}
Mi=⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧⎝⎜⎜⎜⎜⎛10+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0⎠⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎛0+∞+∞+∞+∞+∞10+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0⎠⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎛0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞10+∞+∞+∞+∞0+∞+∞+∞+∞+∞0⎠⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎛0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞10+∞+∞+∞+∞0⎠⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎛0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞1+∞+∞+∞+∞+∞1⎠⎟⎟⎟⎟⎞⎝⎜⎜⎜⎜⎛0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0+∞+∞+∞+∞+∞0⎠⎟⎟⎟⎟⎞si=2si=0si=1si=7si=6si∈/{2,0,1,7,6}
线段树上维护矩阵乘法即可。于是这道题可以单点修改
错因
- 矩阵乘法没有交换律,所以根据我们矩阵乘法的规则,又
M
i
M_i
Mi 在左边,所以从右往左乘才是正常的 DP 过程。因此
PushUp
和Query
中都是rch
乘lch
而不是lch
乘rch
。
代码
#include <algorithm>
#include <cstdio>
#include <cstring>
const int INF = 0x3f3f3f3f;
const int MAXN = 200000;
const int MAXP = 5;
int N, Q;
char S[MAXN + 5];
struct Matrix {
int n, m;
int Mat[MAXP + 1][MAXP + 1];
Matrix(int _n = 0, int _m = 0) {
n = _n, m = _m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
Mat[i][j] = INF;
}
int* operator [] (const int &i) {
return Mat[i];
}
Matrix operator * (Matrix other) {
Matrix ret(n, other.m);
for (int i = 1; i <= ret.n; i++)
for (int j = 1; j <= ret.m; j++)
for (int k = 1; k <= m; k++)
ret[i][j] = std::min(ret[i][j], Mat[i][k] + other[k][j]);
return ret;
}
void Debug() {
for (int i = 1; i <= n; i++, puts(""))
for (int j = 1; j <= m; j++) {
if (Mat[i][j] == INF)
printf("INF\t");
else
printf("%d\t", Mat[i][j]);
}
}
};
struct SegmentTree {
#define lch (u << 1)
#define rch (u << 1 | 1)
Matrix Dp[(MAXN << 2) + 5];
void PushUp(int u) {
Dp[u] = Dp[rch] * Dp[lch];
}
void Build(int u, int lft, int rgt) {
if (lft == rgt) {
Dp[u] = Matrix(5, 5);
for (int i = 1; i <= 5; i++)
Dp[u][i][i] = 0;
switch (S[lft]) {
case '2': Dp[u][1][1] = 1, Dp[u][2][1] = 0; break;
case '0': Dp[u][2][2] = 1, Dp[u][3][2] = 0; break;
case '1': Dp[u][3][3] = 1, Dp[u][4][3] = 0; break;
case '7': Dp[u][4][4] = 1, Dp[u][5][4] = 0; break;
case '6': Dp[u][4][4] = 1, Dp[u][5][5] = 1; break;
}
return;
}
int mid = (lft + rgt) >> 1;
Build(lch, lft, mid);
Build(rch, mid + 1, rgt);
PushUp(u);
}
Matrix Query(int u, int lft, int rgt, int l, int r) {
if (l <= lft && rgt <= r)
return Dp[u];
int mid = (lft + rgt) >> 1;
if (mid < l)
return Query(rch, mid + 1, rgt, l, r);
if (r <= mid)
return Query(lch, lft, mid, l, r);
return Query(rch, mid + 1, rgt, l, r) * Query(lch, lft, mid, l, r);
}
#undef lch
#undef rch
}T;
int main() {
scanf("%d%d%s", &N, &Q, S + 1);
T.Build(1, 1, N);
while (Q--) {
int l, r;
scanf("%d%d", &l, &r);
Matrix Ans = T.Query(1, 1, N, l, r);
if (Ans[5][1] >= INF)
puts("-1");
else
printf("%d\n", Ans[5][1]);
}
return 0;
}