题目

给定两个整数序列 $A$ $B$ ,长度分别为 $n$ $m$ ,且满足 $1\leq A_i,B_i\leq k$ 。现在你希望求出一个满足 $1\leq C_i\leq k$ 的整数序列 $C$ ,它既不是 $A$ 的子序列,也不是 $B$ 的子序列。求 $C$ 的最小长度。

题解

$f_{i,j}$ 表示扫完 $A_i,B_j$ $C$ 的最小长度。

看上去是 $\mathcal{O}(nmk)$ 实际上 $\mathcal{O}(nm)$

代码

const int N = 4010;

inline ll Read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

namespace Main {
	int n, m, K;
	int a[N], b[N];
	int f[N][N], nxta[N][N], nxtb[N][N];
	int main () {
		n = Read(), m = Read(), K = Read();
		for (int i = 1; i <= n; i++) a[i] = Read();
		for (int i = 1; i <= K; i++) nxta[n + 1][i] = n + 1;
		for (int i = n; i >= 0; i--) {
			for (int j = 1; j <= K; j++) nxta[i][j] = nxta[i + 1][j];
			nxta[i][a[i + 1]] = i + 1;
		}
		for (int i = 1; i <= m; i++) b[i] = Read();
		for (int i = 1; i <= K; i++) nxtb[m + 1][i] = m + 1;
		for (int i = m; i >= 0; i--) {
			for (int j = 1; j <= K; j++) nxtb[i][j] = nxtb[i + 1][j];
			nxtb[i][b[i + 1]] = i + 1;
		}
		memset (f, 127 / 3, sizeof f);
		int inf = f[0][0];
		f[0][0] = 0;
		for (int i = 0; i <= n + 1; ++i)
			for (int j = 0; j <= m + 1; ++j) 
				if(f[i][j] < inf)
					for (int k = 1; k <= K; k++) {
						if(nxta[i][k] && nxtb[j][k])
							f[nxta[i][k]][nxtb[j][k]] = min(f[nxta[i][k]][nxtb[j][k]], f[i][j] + 1);
					}
		printf ("%d\n", f[n + 1][m + 1]);
		return 0;
	}
}

int main () {
	string str = "subsequence";
	freopen((str + ".in").c_str(), "r", stdin);
	freopen((str + ".out").c_str(), "w", stdout);
	Main::main();
	return 0;
}
EOF

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。

博客信息

作者
Jayun
时间
2024-02-20 14:44:49
博客类型