题解
f[]维护当前最长的公共子序列,f[i]是这条子序列的第i个数在a中的位置。易知f[]是递增的。
对于b的第i个数b[i],找到其在a中的位置mp[b[i]],如果mp[b[i]]大于f[len],说明b[i]这个数可以加到当前最长子序列后面。
不然的话要想把b[i]这个数加到子序列里,我们可以根据f[]单调的性质二分在f[]中找到mp[b[i]]的位置f[l]。由于同样长的一条链的最后一个元素,他在a[]中出现的位置靠前一些,答案就越不会更差,所以如果f[l]要比mp[b[i]]大,就更新。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n, a[100010], b[100010], mp[100010], f[100010]/*以b[i]为结尾的最长公共子序列在a中的位置*/, len;
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
mp[a[i]] = i;
}
for(int i = 1; i <= n; ++i) scanf("%d", &b[i]);
for(int i = 1; i <= n; ++i){
int l = 0, r = len, mid;
if(mp[b[i]] > f[len]) f[++len] = mp[b[i]];
else{
while(l < r){
mid = l + r >> 1;
if(f[mid] > mp[b[i]]) r = mid;
else l = mid + 1;
}
f[l] = min(mp[b[i]], f[l]);
}
}
printf("%d
", len);
return 0;
}