这道题比 CF10D 更难
CF10D 是可以O(n3) dp过的,但是这个只能O(n2)
n^3的思路是,设置f[i][j]表示 A[i] 与 B[j] 的最长LCIS,当A[i]==B[j]时,判断F[i−1][k(k−>(0,j−1))]的最大值。
因此我们得到以下方程。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | for(i=1;i<=n;i++)for(j=1;j<=m;j++)
 {
 if(a[i]==b[j])
 {
 for(k=0;k<j;k++)
 if(a[i]>b[k]&&f[i][j]<f[i-1][k]+1)  f[i][j]=f[i-1][k]+1;
 }
 else f[i][j]=f[i-1][j];
 }
 
 | 
但是这个复杂度太大了,甚至连T=1,N=1000都过不了,因此我们要想到优化。
我们发现i,j肯定不能省去,因此我们观察k,发现
若果上一个循环刷新了最大值,一旦a[i]>b[j]那么f[i][j]岂不是可以集成之前的f[i−1][j]最大值?
那么我们加一个最大值mx,来统计。
需要注意的是,mx做完j的循环都要清空,因为可能a[i]<a[i−1] 然后mx继承了比他大的数字的LCIS,然后用在了比他小的LCIS上。
比如
2 5 4
2 5 4
就可能出现
f[2][2]=2;
以下就是dp部分。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | for(i=1;i<=n;i++){
 int mx=0;
 for(j=1;j<=m;j++)
 {
 f[i][j]=f[i-1][j];
 if(a[i]==b[j]) f[i][j]=max(f[i][j],mx+1);
 else if(a[i]>b[j]) mx=max(mx,f[i-1][j]);
 ans=max(ans,f[i][j]);
 }
 }
 
 | 
完整版代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 | #include<请勿在代码前添加超长预编译指令>
 using namespace std;
 
 int f[1100][1100];
 int n,m;
 int a[1100],b[1100];
 int t,ans;
 
 int main()
 {
 ios::sync_with_stdio(false);
 int i,j;
 cin>>t;
 for(t;t>=1;t--)
 {
 memset(f,0,sizeof(f));
 ans=0;
 cin>>n;
 for(i=1;i<=n;i++) cin>>a[i];
 cin>>m;
 for(i=1;i<=m;i++) cin>>b[i];
 for(i=1;i<=n;i++)
 {
 int mx=0;
 for(j=1;j<=m;j++)
 {
 f[i][j]=f[i-1][j];
 if(a[i]==b[j]) f[i][j]=max(f[i][j],mx+1);
 else if(a[i]>b[j]) mx=max(mx,f[i-1][j]);
 ans=max(ans,f[i][j]);
 }
 }
 cout<<ans<<endl;
 }
 return 0;
 }
 
 |