【SSL】2666勇闯黄金十二宫射手宫
作者:互联网
【SSL】2666勇闯黄金十二宫射手宫
Time Limit:1000MS
Memory Limit:65536K
Description
第九个他们来到射手宫,身为射手座黄金圣斗士的艾尔里斯是狮子座圣斗士艾尔里亚的哥哥,他早在13年前就发现了撒加杀了真教皇,并且自己做了假教皇。然而他却被撒加迫害致死。现在星矢四人已经来到了射手宫。艾尔里斯的灵魂想考验一下这些圣斗士们的水平,在射手宫的墙上留下了一道题目。 “已知艾尔里斯和弟弟艾尔里亚的基因基本相同,由于基因表达起来不方便,所以就用n个数字来表示。(因为至今共发现100000种基因,所以每个数字都<=100000)兄弟之间的基因个数是相同的,就是说他们都有n个数字。且对于每个人,这n个数字互不相同。现在要求兄弟之间基因的最长公共部分。可以不连续。” 如果,他们解决不了这题,就通不过射手宫了。不过还好,他们顺利地通过了!
Input
本题包含多组数据. 第1行,为n(1<=n<=100000) 下面2行,每行n个数字,表示了一个人的所以基因。
Output
对于每组数据输出一行,为他们两人基因的最长公共部分。
Sample Input
7
1 2 3 4 5 6 7
7 6 5 4 1 2 3
Sample Output
3
思路
这道题是求最长公共子序列。
因为两组数长度相同,所以可以转换成求最长不下降序列。
先把两组数按第一组的顺序排序,再做第二组的最长不下降序列,时间复杂度为n*n,会超时,应该用二分查找。
用一个数组模拟最长不下降序列,从前往后找,如果当前数>=模拟数组中的最后一个,直接往后加。否则二分查找找到一个前一个数<当前数的位置,替换该数。
状态转移方程:
当a[i]>=b[ans],ans+1,b[ans]=a[i]
当a[i]<b[ans],b[w]=a[i]
w是二分查找到位置,1<=i<=n,1<=ans<i,b[0]=0
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int n,d[100010],a[100010],f[100010],len,ans;
void input()
{
int i,t;
len=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&t);
d[t]=i;
}
for(i=1;i<=n;i++)
{
scanf("%d",&t);
if (d[t]>0)
{
len++;
a[len]=d[t];
}
}
return;
}
int erfind(int s)
{
int l=1,r=ans,mid;
do
{
mid=(l+r)/2;
if (f[mid]<s)
{
l=mid+1;
}
else
{
r=mid-1;
}
}
while(l<=r);
return l;
}
void work()
{
int i;
f[1]=a[1];
ans=1;
for(i=2;i<=len;i++)
{
if (a[i]>=f[ans])
{
ans++;
f[ans]=a[i];
}
else
{
f[erfind(a[i])]=a[i];
}
}
printf("%d",ans);
return;
}
int main()
{
input();
work();
return 0;
}
标签:十二宫,int,mid,len,2666,ans,勇闯,include,射手 来源: https://blog.csdn.net/weixin_46975572/article/details/110955550