2014.10.4模拟赛【球的序列】

模拟赛 同时被 3 个专栏收录
30 篇文章 0 订阅
20 篇文章 0 订阅
48 篇文章 0 订阅

球的序列(formation.*)

   N个编号为1-n的球,每个球都有唯一的编号。这些球被排成两种序列,分别为A、B序列,现在需要重新寻找一个球的序列l,对于这个子序列l中任意的两个球,要求j,k(j<k),都要求满足lj在A中位置比lk在A中位置靠前,却lj在B中位置比lk在B中位置靠前,请你计算这个子序列l的最大长度。

输入:

第一行一个整数,表示N。

第二行N个整数,表示A序列。

第三行N个整数,表示B序列。

 

样例输入

5

1 2 4 3 5

5 2 3 4 1

 

样例输出

2

样例说明

L可以是{2,3},也可以是{2,4}

 

数据范围:

40% N<=5000

100% N<=50000

题意就是给你两个1~n的排列,求最长公共子序列

n^2显然dp随便写

但是n是5w级别,所以不能这样搞

考虑到这题特殊之处在于是两个1~n的排列,我们可以把它转换成求最长上升子序列的问题

对于原来的最长公共子序列,要求元素在a数组中的位置是递增的,在b数组中也是递增的

那么我们考虑用s[i]表示b[i]在a数组中的位置

那么在s数组中取下标递增的子序列,在原来的b数组中也是递增的

如果我们再在s中取大小递增的子序列,在原来的a数组中也是递增的(很简单,不会自己yy一下)

所以变成在s数组中做最长上升子序列,这个nlogn就搞定了

当时我就A掉了它

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
int pos[N];
int a[N];
int mn[N];
int n,mx;
inline int search(int x)
{
	int l=1,r=mx;
	int s=0;
	while (l<=r)
	{
		int mid=(l+r)>>1;
		if (mn[mid]<x){s=mid;l=mid+1;}
		else r=mid-1;
	}
	return s;
}
int main()
{
	freopen("formation.in","r",stdin);
	freopen("formation.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		int x;scanf("%d",&x);
		pos[x]=i;
	}
	for (int i=1;i<=n;i++)
	{
		int x;scanf("%d",&x);
		a[i]=pos[x];
	}
	mn[1]=a[1];mx=1;
	for (int i=2;i<=n;i++)
	 {
	 	int find=search(a[i]);
	 	if (find==mx)mn[++mx]=a[i];
	 	else if (mn[find+1]>a[i])mn[find+1]=a[i];
	 }
	printf("%d\n",mx);
}

  • 1
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏

zhb1997

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值