题目的本意是求LCS,但由于每个序列的元素各不相同,所以将A序列重新编号{1,2,,,p+1},将B序列重新编号,分别为B中的元素在A中对应出现的位置(没有的话就是0)。
在样例中就是A = {1 7 5 4 8 3 9},B = {1 4 3 5 6 2 8 9}
重新编号以后:
A = {1 2 3 4 5 6 7}, B = {1 4 6 3 0 0 5 7}(里面的0在求LIS时可以忽略)
这样求A、B的LCS就转变为求B的LIS
求LIS用二分优化,时间复杂度为O(nlogn)
第一次做的用二分求LIS的题是HDU 1025
http://www.cnblogs.com/AOQNRMGYXLMV/p/3862139.html
在这里再复习一遍
1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn = 250 * 250; 9 int num[maxn], s[maxn], dp[maxn]; 10 11 int main(void) 12 { 13 #ifdef LOCAL 14 freopen("10635in.txt", "r", stdin); 15 #endif 16 17 int T, kase; 18 scanf("%d", &T); 19 for(kase = 1; kase <= T; ++kase) 20 { 21 int N, p, q, x; 22 scanf("%d%d%d", &N, &p, &q); 23 memset(num, 0, sizeof(num)); 24 for(int i = 1; i <= p+1; ++i) 25 { 26 scanf("%d", &x); 27 num[x] = i; 28 } 29 int n = 1; 30 for(int i = 1; i <= q+1; ++i) 31 { 32 scanf("%d", &x); 33 if(num[x]) 34 s[n++] = num[x]; 35 } 36 //求s[1]...s[n]的LIS 37 dp[1] = s[1]; 38 int len = 1; 39 for(int i = 2; i <= n; ++i) 40 { 41 int left = 1, right = len; 42 while(left <= right) 43 { 44 int mid = (left + right) / 2; 45 if(dp[mid] < s[i]) 46 left = mid + 1; 47 else 48 right = mid - 1; 49 } 50 dp[left] = s[i]; 51 if(left > len) 52 ++len; 53 } 54 55 printf("Case %d: %d\n", kase, len); 56 } 57 return 0; 58 }