XiaoHuang's Space
XiaoHuang's Space
XiaoHuang
May the force be with you.
『题解』Codeforces10D LCIS
Posted: Dec 11, 2019
Last Modified: Dec 13, 2019
This article was last modified days ago. The content of this post may be outdated!

Portal:

Portal1: Codeforces

Portal2: Luogu

Description

This problem differs from one which was on the online contest.

The sequence $a_1, a_2, \cdots , a_n$ is called increasing, if $a_i < a_{i + 1}$ for $i < n$.

The sequence $s_1, s_2, \cdots , a_n$ is called the subsequence of the sequence $a_1, a_2, \cdots , a_n$, if there exist such a set of indexes $1 \le i_1 < i_2 < \cdots < i_k \le n$ that $a_{i, j} = s_j$. In other words, the sequence $s$ can be derived from the sequence $a$ by crossing out some elements.

You are given two sequences of integer numbers. You are to find their longest common increasing subsequence, i.e. an increasing sequence of maximum length that is the subsequence of both sequences.

Input

The first line contains an integer $n (1 \le n \le 500)$ — the length of the first sequence. The second line contains $n$ space-separated integers from the range $[0, 10^9]$ — elements of the first sequence. The third line contains an integer $m (1 \le m \le 500)$ — the length of the second sequence. The fourth line contains m space-separated integers from the range $[0, 10^9]$ — elements of the second sequence.

Output

In the first line output $k$ — the length of the longest common increasing subsequence. In the second line output the subsequence itself. Separate the elements with a space. If there are several solutions, output any.

Sample Input1

7
2 3 1 6 5 4 6
4
1 3 5 6

Sample Output1

3
3 5 6

Sample Input2

5
1 2 0 2 1
3
1 0 1

Sample Output2

2
0 1

Description in Chinese

求两个序列的最长公共上升子序列。

Solution

用$\texttt{f[i][j]}$表示$\texttt{A}$与$\texttt{B}$构成的以$b_j$为结尾的最长公共上升子序列的长度。

动态转移方程为:

$$f[i][j] = \max_{k = 0}^{j - 1}{(f[i - 1][k] + 1)}, \texttt{其中}B_k < B_j$$

而$k$这一维可以省去,在状态转移后记录最大符合要求的$f[k]$作为下一次的转移,正确性仍旧不变。

所以,最后的时间复杂度为$O(n^2)$。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>

using namespace std;

const int MAXN = 505;
int n, m, a[MAXN], b[MAXN], ans[MAXN], dp[MAXN], scheme[MAXN];
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    scanf("%d", &m);
    for (int i = 1; i <= m; i++)
        scanf("%d", &b[i]);
    for (int i = 1; i <= n; i++) {//动态规划主要部分
        int id = 0;
        for (int j = 1; j <= m; j++) {
            if (a[i] == b[j]) {
                dp[j] = dp[id] + 1;
                scheme[j] = id;
            }
            if (a[i] > b[j] && dp[id] < dp[j]) id = j;
        }
    }
    int id = 0;
    for (int i = 1; i <= m; i++)
        if (dp[i] > dp[id]) id = i;
    printf("%d\n", dp[id]);
    int top = 0;
    while (dp[id]--) {
        ans[++top] = b[id];
        id = scheme[id];
    }
    for (int i = top; i >= 1; i--)
        printf("%d ", ans[i]);//输出方案前需要记录
    return 0;
}
Article License: CC BY-NC-ND 4.0
Article Author: XiaoHuang
  1. 1. Portal:
  2. 2. Description
  3. 3. Input
  4. 4. Output
  5. 5. Sample Input1
  6. 6. Sample Output1
  7. 7. Sample Input2
  8. 8. Sample Output2
  9. 9. Description in Chinese
  10. 10. Solution
  11. 11. Code
Newer Post
『题解』UVa11324 The Largest Clique
Older Post
『题解』Codeforces2A Winner
Buy me a beer?
-->
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×