【题解】P1439 【模板】最长公共子序列

P1439 【模板】最长公共子序列

题解

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\n", len);
	return 0;
}
posted @ 2021-03-07 09:27  _Buffett  阅读(56)  评论(0编辑  收藏  举报