[不知道哪来的题] Subsequence

Description

给出两个由小于等于 \(k\) 的正整数构成的数列 \(A\)\(B\) ,长度为 \(n\)\(m\)

现在需要一个由小于等于 \(k\) 的正整数构成的数列 \(C\) ,使得 \(C\) 既不是 \(A\) 的子序列,也不是 \(B\)
的子序列。

请求出 \(C\) 的最小长度。

\(n,m,k\le 4000\)

Solution

\(dp[i][j]\) 表示 \(A\) 扫到 \(i\)\(B\) 扫到 \(j\)\(C\) 的最小长度。

预处理一下下一个与当前位置值相同的位置就好了。

#include<bits/stdc++.h>
using namespace std;

template <class T> inline void read(T &x) {
	x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
	for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
}

#define N 4010
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drp(i, a, b) for (int i = a; i >= b; i--)

int n, m, K, a[N], b[N], dp[N][N], f1[N][N], f2[N][N], ans;

inline void upd(int& x, int y) { if (!x || x > y) x = y; }

int main() {
	read(n), read(m), read(K);
	rep(i, 1, n) read(a[i]);
	rep(i, 1, m) read(b[i]);
	drp(i, n, 1) {
		rep(j, 1, K) f1[i][j] = f1[i + 1][j];
		f1[i][a[i]] = i;
	}
	drp(i, m, 1) {
		rep(j, 1, K) f2[i][j] = f2[i + 1][j];
		f2[i][b[i]] = i;
	}
	dp[0][0] = 1, ans = min(n, m) + 1;
	rep(i, 0, n) rep(j, 0, m) if (a[i] == b[j] && dp[i][j]) rep(k, 1, K)
		if (!f1[i + 1][k] && !f2[j + 1][k]) ans = min(ans, dp[i][j]);
		else upd(dp[f1[i + 1][k]][f2[j + 1][k]], dp[i][j] + 1);
	printf("%d", ans);
	return 0;
}
posted @ 2018-06-10 20:05  aziint  阅读(146)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.