LCS<-->LIS+二分
这道题是明显的LCS,但是250*250的数据量又使得LCS的算法行不通,
所以我们需要转化,d
通过参照原则可以参照a写出新的b数组,其中b中的每个数如果在a中出现了,则b数组该位置的数为在a中的位置,如果没有在a中出现的话,则该位置标为0.
这样的话,我们只需要求b数列的LIS即可了,这样我们使用LIS复杂度为O(nlog(N))的算法就降低了复杂度。
算法解释见http://blog.csdn.net/shankeliupo/article/details/9404303
代码如下;#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int M = 250*250; int p, q, n, a[M], c[M], b[M], dp[M]; int search(int l, int r, int x) { int mid; while(l<=r) { mid = (l+r)/2; if(x==c[mid]) return mid; else if(x>c[mid]) l = mid+1; else r = mid-1; } return l; } int main () { int x, t, k = 0; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&p,&q); memset(a,0,sizeof(a)); for(int i = 1; i <= p+1; i++) {scanf("%d",&x); a[x] = i; } for(int i = 1; i <= q+1; i++) {scanf("%d",&x); b[i] = a[x]; } c[1] = b[1]; dp[1] = 1; int j, size = 1; for(int i = 2; i <= q+1; i++) { if(b[i]<c[1]) j = 1; else if(b[i]>c[size]) j = ++size; else j = search(1,size,b[i]); c[j] = b[i]; dp[i] = j; } printf("Case %d: %d\n",++k ,size); } return 0; }