[Luogu P1439] LCS升级版

badge:

普通O(n^2)很容易想到,但是TLE。

#include<cstdio>
using namespace std;
int a[1010],b[1010],dp[1010][1010];
int maxf(int x,int y){return x>y?x:y;}
int minf(int x,int y){return x<y?x:y;}
int main()
{
    int n,m,i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)scanf("%d",&b[i]);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            dp[i][j]=maxf(dp[i][j],maxf(dp[i-1][j],dp[i][j-1]));
            if(a[i]==b[j])
            dp[i][j]=maxf(dp[i][j],dp[i-1][j-1]+1);
        }
    }
    printf("%d\n",dp[n][n]);
    return 0;
}

我们思考这题的关键点:两个序列都是1~n的排列。

排列?这意味着两个序列里数都一样,只是位置不同。

有点类似于友好城市,只需要求一堆不相交的配对即可。

画出图来,把右边的序列按照左边每个数所在的位置重新填好,求一个最长上升子序列即可。

即:记录a序列里每个数填的位置f[a[i]]=i,然后把b[i]赋成f[b[i]]。在b序列里O(nlogn)求一下LIS即可。

#include<cstdio>
using namespace std;
int a[1000010],b[1000010];
int c[1000010],f[1000010],tot;
int pos(int l,int r,int val)
{
    int mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(c[mid]>val)r=mid-1,ans=mid;
        else l=mid+1;
    }
    return ans;
}
int main()
{
    int n,m,i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    for(i=1;i<=n;i++)scanf("%d",&b[i]);
    for(i=1;i<=n;i++)f[a[i]]=i;
    for(i=1;i<=n;i++)b[i]=f[b[i]];
    //for(i=1;i<=n;i++)printf("%d ",f[i]);printf("\n");
    //for(i=1;i<=n;i++)printf("%d ",b[i]);printf("\n");
    c[++tot]=b[1];
    for(i=2;i<=n;i++)
    {
        if(b[i]>c[tot])c[++tot]=b[i];
        else
        {
            k=pos(1,tot,b[i]);
            //printf("found pos %d\n",k);
            c[k]=b[i];
        }
    }
    printf("%d\n",tot);
    return 0;
}
/*
5
3 2 1 4 5
1 2 3 4 5
*/

原文地址:https://www.cnblogs.com/Rain142857/p/11793970.html

时间: 2024-11-09 01:50:19

[Luogu P1439] LCS升级版的相关文章

HDU 1503 Advanced Fruits (LCS升级版)

题目大意:将两个字符串结合起来,他们的公共子串只输出一次 根据LCS的原理,将每个字符都进行标记,看两个字符串中对应的字符究竟处于什么状态,然后输出,其标记为公共子串的字符只输出一次即可,也是一道模板题了. http://blog.csdn.net/libin56842/article/details/9618529 #include <stdio.h> #include <string.h> #include <algorithm> using namespace s

luogu P1439 【模板】最长公共子序列

题目qwq (第一道蓝题) 据说是用了hash的思想(?) 总之是先把第一个序列每个数出现的顺序记下来(其实第一个序列的数字不用记), 然后第二个序列的每个数都对照它的顺序,这样只要得到一个升序的序列就行了qwq 如果遇到出现顺序在前面的数,就用二分法找一下它的位置,然后把原来存下来的顺序覆盖掉 #include<cstdio> using namespace std; int f[100005],ans[100005]; int n,sum; int k,l,r,now,mid; int m

Luogu 1439 【模板】最长公共子序列

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例#1: 5 3 2 1 4 5 1 2 3 4 5 输出样例#1: 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 [题解] 首先不难想到的是将其转化成一个序列的最长上升子序列 由于两个序列均为1~n的排列,在将其中一个

P1439 排列LCS问题

P1439 排列LCS问题 56通过 220提交 题目提供者yeszy 标签二分动态规划 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 暂时没有讨论 题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例#1: 5 3 2 1 4 5 1 2 3 4 5 输出样例#1: 3 说明 [数据规模] 对于50%的数

[洛谷P1439]排列LCS问题

题目大意:给你两个1~n的排列,求他们的LCS. 解题思路:由于是1~n的排列,每个数会且只会出现1次.我们可以把一个序列映射成1,2,3,4……然后将另一个序列按照这个映射进行改变.由于前一个序列已经有序,那么后一个序列的最长上升子序列(LIS)肯定是前一个的子序列,由于LIS最长,所以它的值也是LCS的值.故我们只要这样做一遍LIS即可.用单调队列优化后的LIS,时间复杂度$O(n\log n)$. C++ Code: #include<cstdio> #include<algori

luogu P1579 哥德巴赫猜想(升级版)

题目描述 一个等差数列是一个能表示成a, a+b, a+2b,..., a+nb (n=0,1,2,3,...)的数列. 在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平方的数的集合,其中p和q为非负整数)S中长度为n的等差数列. 输入输出格式 输入格式: 第一行: N(3<= N<=25),要找的等差数列的长度. 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M

[Luogu 1919]【模板】A*B Problem升级版(FFT快速傅里叶)

Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出一行,即x*y的结果.(注意判断前导0) Sample Input 134 Sample Output 12 HINT n<=60000 题解 A*B Problem.和 A+B Problem 一样简单. 1 input() and print(int(input()) * int(input()

luogu P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

模板 嗯 做多项式乘法,进位 没了 #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define pi acos(-1.0) inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9')c = getchar(); while(c <= '9'

luogu P1919 【模板】A*B Problem升级版(FFT快速傅里叶)|FFT

题目描述 给你两个正整数 a,b,求 a×b. 输入格式 第一行一个正整数,表示 a: 第二行一个正整数,表示 b. 输出格式 输出一行一个整数表示答案. #include<cmath> #include<string> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int _=4e6+10; const double Pi=a