LCIS
分析:
- 最长公共上升子序列
- 先按常规打下来 O ( n 3 ) O(n^3) O(n3)
- f i , j f_{i,j} fi,j 表示以 a [ i ] , b [ j ] a[i],b[j] a[i],b[j] 结尾( a [ i ] , b [ j ] a[i],b[j] a[i],b[j]作为最后的结尾)的 L C I S LCIS LCIS
O ( n 3 ) O(n^3) O(n3)
#include <bits/stdc++.h>
using namespace std;
const int N=3005;
int a[N],b[N],f[N][N];
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n,m;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
m=n;
for(int i=1;i<=m;i++) cin>>b[i];
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i]==b[j])
{
for(int k=0;k<j;k++) // 去找最长的子状态
{
if(b[k]<b[j]) f[i][j]=max(f[i][j],f[i-1][k]+1);
}
ans=max(ans,f[i][j]);
}
else f[i][j]=f[i-1][j];
}
}
cout<<ans<<endl;
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%-3d",f[i][j]);
}printf("\n");
}*/
return 0;
}
/*
10
1 5 3 6 3 2 7 3 6 2
9 6 2 3 1 5 3 3 6 1
*/
-
显然会超时,考虑哪里还能优化
找最长子状态的时候,做了很多遍重复操作,发现最长子状态是能够继承的(j下标后移时,最长子状态只会更大,因此便不用去遍历查询了)
O ( n 2 ) O(n^2) O(n2)
#include <bits/stdc++.h>
using namespace std;
const int N=3005;
int a[N],b[N],f[N][N];
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n,m;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
m=n;
for(int i=1;i<=m;i++) cin>>b[i];
int ans=0;
for(int i=1;i<=n;i++)
{
int val=0; // val表示当前最大子状态
for(int j=1;j<=m;j++)
{
if(a[i]==b[j]) f[i][j]=val+1;
else f[i][j]=f[i-1][j];
// j即将增大为j+1,检查j能否更新val
if(b[j]<a[i]) val=max(val,f[i-1][j]);
ans=max(ans,f[i][j]);
}
}
cout<<ans<<endl;
return 0;
}
滚动数组优化
#include <bits/stdc++.h>
using namespace std;
const int N=3005;
int a[N],b[N],dp[N];
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n,m;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
m=n;
for(int i=1;i<=m;i++) cin>>b[i];
int ans=0;
for(int i=1;i<=n;i++)
{
int val=0; // val表示当前最大子状态
for(int j=1;j<=m;j++)
{
if(a[i]==b[j]) dp[j]=val+1;
// j即将增大为j+1,检查j能否更新val
if(b[j]<a[i]) val=max(val,dp[j]);
ans=max(ans,dp[j]);
}
}
cout<<ans<<endl;
return 0;
}