• 2014.10.4模拟赛【球的序列】


    球的序列(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
    ",mx);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    php函数名后冒号(:)+数据类型(返回值类型限制/php新特性)
    qBittorrent 任务数
    TDDFT软件 octopus 编译
    visual studio code, latex workshop, setting.json
    Tex插入图片/插入tikz流程图
    记录一下讨厌的东西,就当黑名单了
    安装mingw-w64
    win7 和 win10窗口的小区别
    lattice, reciprocal lattice, OUTCAR
    v_sim 个人用户编译 无root权限
  • 原文地址:https://www.cnblogs.com/zhber/p/4035890.html
Copyright © 2020-2023  润新知