【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;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值