题解LCIS
Posted kcn999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解LCIS相关的知识,希望对你有一定的参考价值。
题目描述
给定两个整数序列,写一个程序求它们的最长上升公共子序列。
输入格式
每个序列用两行表示,第一行是长度L,第二行是该序列。
输出格式
在第一行,输出该LCIS的长度。第二行,输出该LCIS。
输入样例
5
1 4 2 5 -12
4
-12 1 2 4
输出样例
2
1 4
题解
表面上看起来是个$O(n^4)$,但实际上可以优化到$O(n^2)$(貌似还可以用树状数组优化到$O(nlogn)$)
我们设$dp[i][j]$为以$a_1$到$a_i$中的一个数和$b_j$为结尾的LCIS,容易得到$dp[i][j] = \underset1 \leqslant k < jmax \left \ dp[j - 1][k] + 1 \right \$。
其实我们可以在枚举$i$、$j$的时候顺便维护$\underset1 \leqslant k < jmax \left \ dp[j - 1][k] + 1 \right \$,这样就把时间复杂度降到$O(n^2)$了。
观察方程,其实我们第一位只会用到$i - 1$和$i$,这里又可以用滚动数组优化。
![技术图片](/img/jia.gif)
#include <iostream> #define MAX_N (500 + 5) #define MAX_M (500 + 5) using namespace std; int n, m; int a[MAX_N], b[MAX_M]; int dp[MAX_M]; int p[MAX_M]; int ans; void LCIS(int x) if(p[x]) LCIS(p[x]); cout << b[x] << " "; return; int main() cin >> n; for(register int i = 1; i <= n; ++i) cin >> a[i]; cin >> m; for(register int i = 1; i <= m; ++i) cin >> b[i]; int pos = 0, tmp; for(register int i = 1; i <= n; ++i) tmp = 0; for(register int j = 1; j <= m; ++j) if(a[i] > b[j] && dp[j] > dp[tmp]) tmp = j; if(a[i] == b[j]) dp[j] = dp[tmp] + 1; p[j] = tmp; for(register int i = 1; i <= m; ++i) if(dp[i] > dp[pos]) pos = i; cout << dp[pos] << "\n"; if(dp[pos]) LCIS(pos); return 0;
以上是关于题解LCIS的主要内容,如果未能解决你的问题,请参考以下文章