题目链接
http://noi-test.zzstep.com/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%BE%8B%E9%A2%98/5101%20LCIS
分析
类比LCS和LIS,设状态 f [ i ] [ j ] f[i][j] f[i][j] 表示在 A [ 1... i ] A[1 ... i] A[1...i] 和 B [ 1... j ] B[1 ... j] B[1...j] 中且以 B [ j ] B[j] B[j] 结尾的LCIS;
若 A [ i ] ≠ B [ j ] A[i] \ne B[j] A[i]=B[j], f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j] = f[i - 1][j] f[i][j]=f[i−1][j];
若 A [ i ] = B [ j ] A[i] = B[j] A[i]=B[j], f [ i ] [ j ] = f [ i − 1 ] [ k ] + 1 f[i][j] = f[i - 1][k] + 1 f[i][j]=f[i−1][k]+1,其中 k < j k < j k<j 且 B [ k ] < B [ j ] = A [ i ] B[k] < B[j] = A[i] B[k]<B[j]=A[i];
一般可以写三层循环来完成递推,但因为将枚举 A A A 中元素放在最外层,
每次处理完一个 B B B 中元素,可以将其与 A [ i ] A[i] A[i] 比较来更新答案可能的来源。
输入数据中过多的负数会将读入优化卡炸。
AC代码
#include <cstdio>
const int maxn = 3e3 + 5;
int a[maxn], b[maxn], f[maxn][maxn];
int main() {
int n = read(), ans = 0;
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
for (int i = 1; i <= n; ++i) {
int v = 0;
for (int j = 1; j <= n; ++j) {
if (a[i] == b[j]) f[i][j] = v + 1;
else f[i][j] = f[i - 1][j];
if (b[j] < a[i] && f[i - 1][j] > v) v = f[i - 1][j];
}
}
for (int i = 1; i <= n; ++i)
if (f[n][i] > ans) ans = f[n][i];
printf("%d", ans);
return 0;
}