题目大意

给定两个分别长 n,mn,m 的序列 {a},{b}\{a\},\{b\},求其最长公共上升子序列。

分析

DP(i,j)DP(i, j) 为序列 aa 中的前 ii 个元素,以 bjb_j 结尾时的最长子序列长度。

  • 如果 ai=bja_i = b_j,则 DP(i,j)=maxk<jbk<bj(DP(i,k))+1DP(i, j) = \max\limits_{k<j \land b_k < b_j}(DP(i,k)) + 1
  • 否则 DP(i,j)=DP(i1,j)DP(i, j) = DP(i - 1, j)

这个东西可以滚动数组优化。

int main() {
	int n;
	std::cin >> n;
	V<int> a(n + 1);
	for (int i = 1; i <= n; i++) {
		std::cin >> a[i];
	}
	int m;
	std::cin >> m;
	V<int> b(m + 1);
	for (int j = 1; j <= m; j++) {
		std::cin >> b[j];
	}
	V<int> dp(m + 1), pre(m + 1, -1);
	for (int i = 1; i <= n; i++) {
		int p = 0;
		for (int j = 1; j <= m; j++) {
			if (a[i] == b[j]) {
				dp[j] = dp[p] + 1, pre[j] = p;
			} else if (a[i] > b[j] && dp[p] < dp[j]) {
				p = j;
			}
		}
	}
	int p = std::max_element(dp.begin(), dp.end()) - dp.begin();
	V<int> ans;
	while (p > 0) {
		ans.push_back(b[p]);
		p = pre[p];
	}
	std::reverse(ans.begin(), ans.end());
	std::cout << ans.size() << '\n';
	for (auto i : ans) {
		std::cout << i << ' ';
	}
	return 0;
}

全部代码请看:Codeforces/other/10D.cpp