[CodeForces 750E] New Year and Old Subsequence(动态 DP) | 错题本

文章目录

题目

CF750E New Year and Old Subsequence

分析

d p [ i ] [ 0 / 1 / 2 / 3 / 4 ] dp[i][0/1/2/3/4] 表示前 i i 个数字只能依次匹配到 ϕ / { 2 } / { 2 , 0 } / { 2 , 0 , 1 } / { 2 , 0 , 1 , 7 } \phi/\{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} 构造转移矩阵 M i M_i 使得 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} 其中矩阵乘法定义改变 + min , × + + \to \min, \times \to +
不难发现 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}

线段树上维护矩阵乘法即可。于是这道题可以单点修改

错因

  • 矩阵乘法没有交换律,所以根据我们矩阵乘法的规则,又 M i M_i 在左边,所以从右往左乘才是正常的 DP 过程。因此 PushUpQuery 中都是 rchlch 而不是 lchrch

代码

#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;
}

猜你喜欢

转载自blog.csdn.net/C20190102/article/details/107606203
今日推荐