Description
给你两条路径,对于每条路径上的点各不相同,请你求出两条路径最长公共部分的长度。 Input
第一行是数据组数t 每组数据的第一行包含三个数,n,p,q。其中路径上的点的大小不会超过n^2. 第二行包含p+1个数,表示第一条路径 第三行包含q+1个数,表示第二条路径。 Output见样例。输出最长路径长度。
将A中元素重新标号,例如,样例中
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} .
所以B中的任意一个最长递增子序列都是A和B的公共子序列,所以问题便转换成了一个求解最长递增子序列的问题。而且因为p,q高达62500,要用nlogn的算法求解
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int t,n,p,q,len,a[N],b[N],tot,c[N],index_,saber,num[N],d[N],cnt;
int main()
{
cin>>t;
while(t--)
{
saber=tot=0;
memset(num,0,sizeof(num));
scanf("%d%d%d",&n,&p,&q);
for(int i=1;i<=p+1;i++) scanf("%d",&a[i]),num[a[i]]=i;
for(int i=1;i<=q+1;i++)
{
scanf("%d",&b[i]);
if(num[b[i]])
{
tot++;
c[tot]=num[b[i]];
}
}
saber=1;
d[1]=c[1];
for(int i=2;i<=tot;i++)
{
if(c[i]>d[saber])
d[++saber]=c[i];
else
{
index_=lower_bound(d+1,d+saber+1,c[i])-d;
d[index_]=c[i];
}
}
cout<<"Case "<<++cnt<<": ";
cout<<saber<<endl;
}
return 0;
}