• 洛谷P1439 排列LCS问题


    题目描述

    给出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

    分析:经典的LCS做法只有50分,100分的做法很显然是O(nlogn)的,将n改为logn能想到的就是二分,但是在LCS问题中要求的是最长公共的,并不满足二分的性质,只有是单调的才能用二分,考虑转化为LIS来做,如果两个序列都是单调上升的,那么答案就是第二个序列的最长上升子序列,关键是题目给的并不是单调上升的,怎么解决呢?我们把第一个序列编号,然后第二个序列按照第一个序列的编号来改动一下,这样第一个序列就是单调上升的了,我们只需要找到第二个序列的最长上升子序列就好了.

          知道要二分,但是要二分什么东西呢?有一种神奇的做法,维护一个栈,考虑第i个元素j,如果j大于栈顶元素,则直接放到栈顶,否则二分找到第一个大于j的数,用j把他替换掉,答案就是栈的大小.原理是什么呢?因为我们是从左往右扫的,根据贪心思想,最后一个数越小越好,替换操作并不是真的替换,而是表示以后的数可以插入在这个位置,毕竟我们只要栈大小,不要求具体的数.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    int n,s1[100010],s2[100010],st[100010],top,mm[100010];
    
    int erfen(int x)
    {
        int l = 1,r = top;
        while (l < r)
        {
             int mid = (l + r) >> 1;
             if (st[mid] <= x)
             l = mid + 1;
             else
             r = mid;
        }
        return r;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
        scanf("%d",&s1[i]);
        for (int i = 1; i <= n; i++)
        scanf("%d",&s2[i]);
        for (int i = 1; i <= n; i++)
        mm[s1[i]] = i;
        for (int i = 1; i <= n; i++)
        s2[i] = mm[s2[i]];
    
        for (int i = 1; i <= n; i++)
        {
            if (s2[i] > st[top])
            st[++top] = s2[i];
            else
            st[erfen(s2[i])] = s2[i];
        }
        printf("%d
    ",top);
    
        return 0;
    }
  • 相关阅读:
    影响CSS的margin合并的几个属性
    Mouse w/o Borders实现两台主机共用一套键鼠方法及问题处理
    隐藏"Input"标签默认样式
    如何快速开发网站?
    如何让Web.xml变得简洁?
    关于中文处理方面的研究
    Hello,World 百态
    UI开发的终极解决方案
    构建网络爬虫?so easy
    MDA数据校验规则定义
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7478186.html
Copyright © 2020-2023  润新知