2334: 【提高】最长公共子序列(LCS)(2)

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:1 解决:1

题目描述

给出 lns="http://www.w3.org/1998/Math/MathML">1 的两个排列 lns="http://www.w3.org/1998/Math/MathML">1 和 lns="http://www.w3.org/1998/Math/MathML">2,求它们的最长公共子序列。

和最长公共子序列(LCS)(1)问题不同的是,本题的 lns="http://www.w3.org/1998/Math/MathML"> 在 lns="http://www.w3.org/1998/Math/MathML">5100000 之间。

输入

第一行是一个数 lns="http://www.w3.org/1998/Math/MathML"> ;(lns="http://www.w3.org/1998/Math/MathML"> 是 lns="http://www.w3.org/1998/Math/MathML">5100000 之间的整数)

接下来两行,每行为 lns="http://www.w3.org/1998/Math/MathML"> 个数,为自然数 lns="http://www.w3.org/1998/Math/MathML">1 的一个排列(lns="http://www.w3.org/1998/Math/MathML">1 的排列每行的数据都是 lns="http://www.w3.org/1998/Math/MathML">1 之间的数,但顺序可能不同,比如 lns="http://www.w3.org/1998/Math/MathML">15 的排列可以是:lns="http://www.w3.org/1998/Math/MathML">1 lns="http://www.w3.org/1998/Math/MathML">2 lns="http://www.w3.org/1998/Math/MathML">3 lns="http://www.w3.org/1998/Math/MathML">4 lns="http://www.w3.org/1998/Math/MathML">5,也可以是 lns="http://www.w3.org/1998/Math/MathML">2 lns="http://www.w3.org/1998/Math/MathML">5 lns="http://www.w3.org/1998/Math/MathML">4 lns="http://www.w3.org/1998/Math/MathML">3 lns="http://www.w3.org/1998/Math/MathML">1)。

输出

一个整数,即最长公共子序列的长度。

样例输入 复制

5 
3 2 1 4 5
1 2 3 4 5

样例输出 复制

3

提示

数据范围

对于 lns="http://www.w3.org/1998/Math/MathML">50% 的数据,lns="http://www.w3.org/1998/Math/MathML">1000

对于 lns="http://www.w3.org/1998/Math/MathML">100% 的数据,lns="http://www.w3.org/1998/Math/MathML">100000

#include<bits/stdc++.h>

using namespace std;
const int N = 100100;
int a[N], b[N], c[N], dp[N];
int n, i;
int main() {
    cin >> n;
    for (i = 1; i <= n; i++) {
        scanf("%d", & a[i]);
        c[a[i]] = i; //求出a数组的每个数的位置
    }
    for (i = 1; i <= n; i++) scanf("%d", & b[i]);
    //求b数组的每个数在a数组的位置(c[b[i]])的 LIS
    dp[1] = c[b[1]];
    //边界
    int len = 1;
    int l, r, mid; //从第2个数开始讨论
    for (i = 2; i <= n; i++) { //增加 LIS的长度
        if (c[b[i]] > dp[len]) {
            len++;
            dp[len] = c[b[i]];
        } else {
            l = 1;
            r = len;
            while (l <= r) {
                mid = (l + r) / 2;
                if (c[b[i]] <= dp[mid]) r = mid - 1;
                else l = mid + 1;
            }
            dp[l] = c[b[i]];
        }
    }
    cout << len;
    return 0;
}