通过读题可以发现,这道题对于 50 % 50\% 50% 的数据可以用普通的 LCS 来解决,而对于 100 % 100\% 100% 的数据,我们就得考虑改变题目了。
我们可以当最长公共子序列都来自排列 P 1 P_1 P1,那么我们把 P 1 P_1 P1 重新标号,比如样例:
3 2 1 4 5
我们把 3 3 3 标号成 1 1 1 把 2 2 2 标号成 1 1 1 ……
我们可以标号成:
1 2 3 4 5
我们在把 P 2 P_2 P2 重新标号变为:
3 2 1 4 5
可以发现, P 1 , P 2 P_1,P_2 P1,P2 重新标号后,性质是一样的,也就是我们要求出重新标号的 P 2 P_2 P2 的 LIS 就行了。
方法一(普通求 LIS 加位运算优化):
不加位运算优化可得 50 50 50 分,加了可得 60 60 60 分。
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define ll long long
#define ull unsigned long long
#define db double
#define x first
#define y second
#define fast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define endl '\n'
#define pb push_back
#define swap(a,b) a=a^b,b=a^b,a=a^b
#define mem(x,a) memset(x,a,sizeof(x))
#define rep(l,r,i) for(int i=l,END##i=r;i<=END##i;i++)
#define per(r,l,i) for(int i=r,END##i=l;i>=END##i;i--)
#define sc scanf
#define pr printf
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
using namespace std;
const int MAXN=1e5+10;
int n,a[MAXN],b[MAXN],dp[MAXN],p[MAXN],t[MAXN];
int main(){
fast
cin>>n;
rep(1,n,i)cin>>a[i];
rep(1,n,i)cin>>b[i];
rep(1,n,i)t[a[i]]=i;
rep(1,n,i)p[i]=t[b[i]];
int ans=0;
rep(1,n,i){
int t=0;
rep(1,i-1,j)
p[i]>p[j]?(t=t>dp[j]?t:dp[j]):0;
dp[i]=t+1;
ans=max(ans,dp[i]);
}
cout<<ans<<"\n";
return 0;
}
方法二(二分优化 LIS):
#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define ll long long
#define ull unsigned long long
#define db double
#define x first
#define y second
#define fast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define endl '\n'
#define pb push_back
#define swap(a,b) a=a^b,b=a^b,a=a^b
#define mem(x,a) memset(x,a,sizeof(x))
#define rep(l,r,i) for(int i=l,END##i=r;i<=END##i;i++)
#define per(r,l,i) for(int i=r,END##i=l;i>=END##i;i--)
#define sc scanf
#define pr printf
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
using namespace std;
const int MAXN=1e5+10,INF=0x3f3f3f3f;
int n,a[MAXN],b[MAXN],q[MAXN],p[MAXN],t[MAXN],len;
int main(){
cin>>n;
rep(1,n,i)cin>>a[i];
rep(1,n,i)cin>>b[i];
rep(1,n,i)t[a[i]]=i;
rep(1,n,i)p[i]=t[b[i]];
q[len]=-INF;
rep(1,n,i){
if(p[i]>q[len])q[++len]=p[i];
else{
int l=1,r=len;
while(l<r){
int mid=l+r>>1;
if(q[mid]>p[i])r=mid;
else l=mid+1;
}
q[l]=p[i];
}
}
cout<<len<<"\n";
return 0;
}