二刷提高课,题解目录在这里— 提高课的题解目录
最长公共上升子序列问题结合了最长上升序列与最长公共序列问题
若我们像最长公共序列一样用f[i][j]来表示a到i,b到j内所选最长的显然不合适
因为少了上升这个限制,所以需要多加一条这里为选的是以b[j]结尾
可以知道我们最后枚举j所以肯定能找到最长的答案
当我们进行状态转移时,不选取a[i]时用f[i-1][j]即可
而当选取a[i]时(前提是相等),对于j来说要看前面所有小于b[j]的最大值
优化:因为我们枚举k的时候只有在a[i]==b[j]时用
而在每一重循环a[i]是不变的,所以我们在枚举j时加一个判断,如果比a[i]小
我们就对其进行判断是否比当前的最大值大若大就选它,避免了多次从头枚举
#include<iostream>
using namespace std;
const int N=3010;
int a[N],b[N];
int f[N][N];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)
{
int maxx=1;//加上了原本的那个
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])f[i][j]=max(f[i][j],maxx);
if(a[i]>b[j])maxx=max(maxx,f[i-1][j]+1);//因为如果不等其实f[i][j]==f[i-1][j]
}
}
int res=0;
for(int i=1;i<=n;i++)res=max(res,f[n][i]);
cout<<res;
return 0;
}