这题很明显的是LCS,不过p, q太大,普通的O(n ^ 2 )算法显然会超时
这里可以把LCS问题转换成LIS问题,LIS有nlogn的算法,然后复杂度就下来了.
因为每个序列都是没重复的,所以可以把序列1重新编号成1 - p + 1,然后序列2按照序列1的数字的对应编号进行转换.
例如:
序列1{1 7 5 4 8 3 9} 编号后变成{1 2 3 4 5 6 7}
序列2{1 4 3 5 6 2 8 9}转换后变成{1 4 6 0 3 0 0 5 7}
去掉转换后的序列2中的0,因为王子没有踩到这个格子.
对转换后的序列2求LIS就可以了.
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <memory.h>
using namespace std;
const int maxn = 62555;
int tb[maxn];
int A[maxn], d[maxn], g[maxn];
int p, q;
int main(){
int T, trash, cas = 1;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &trash, &p, &q);
memset(tb, 0, sizeof(tb));
for(int i = 0; i < p + 1; ++i){
int t = 0;
scanf("%d", &t);
tb[t] = i + 1;
}
int n = 0, ans = 0;
for(int i = 0; i < q + 1; ++i){
int t;
scanf("%d", &t);
if(tb[t]){
A[n++] = tb[t];
}
}
memset(g, 0X20, sizeof(g));
for(int i = 0; i < n; ++i){
int k = lower_bound(g + 1, g + n + 1, A[i]) - g;
d[i] = k;
g[k] = A[i];
ans = max(ans, d[i]);
}
printf("Case %d: %d\n", cas++, ans);
}
return 0;
}

本文介绍了一种将最长公共子序列(LCS)问题转化为最长递增子序列(LIS)问题的方法,并通过nlogn算法实现优化。通过重新编号及去除无效元素,有效地降低了算法的时间复杂度。

3099

被折叠的 条评论
为什么被折叠?



