【luogu1439】 【模板】最长公共子序列 [动态规划][LIS最长上升子序列][离散化]

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

此思路详见luogu第一个题解 一个很妙的离散化

刘汝佳蓝书上面的LIS 详见蓝书

d[i]以i为结尾的最长上升子序列的长度     g[i]表示d值为i的最小状态的编号即长度为i的上升子序列的最小末尾值

1 for(int i=1;i<=n;++i) scanf("%d",&a[i]);
2 for(int i=1;i<=n;++i)
3 {
4     int k=lower_bound(g+1,g+1+n,a[i])-g;
5     d[i]=k;
6     g[k]=cb[i];
7 }

只是手写二分的时候要注意超多细节 巨难受

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define rg register
 4 const int N=100000+5,inf=0x3f3f3f3f;
 5 int n,a[N],b[N],ca[N],cb[N];
 6 int g[N],d[N],len=0;
 7
 8 template<class t>void rd(t &x)
 9 {
10     x=0;int w=0;char ch=0;
11     while(!isdigit(ch)) w|=ch==‘-‘,ch=getchar();
12     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
13     x=w?-x:x;
14 }
15
16 int main()
17 {
18     rd(n);
19     memset(g,inf,sizeof(g));
20     for(rg int i=1;i<=n;++i) rd(a[i]),ca[a[i]]=i;
21     for(rg int i=1;i<=n;++i) rd(b[i]),cb[i]=ca[b[i]];
22     for(rg int i=1;i<=n;++i)
23     {
24         int k=lower_bound(g+1,g+1+n,cb[i])-g;
25         g[k]=cb[i];
26         len=max(len,k);
27     }
28     printf("%d",len);
29     return 0;
30 } 

100昏 用lower_bound

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define rg register
 4 const int N=100000+5,inf=0x3f3f3f3f;
 5 int n,a[N],b[N],ca[N],cb[N];
 6 int g[N],len=0;
 7
 8 template<class t>void rd(t &x)
 9 {
10     x=0;int w=0;char ch=0;
11     while(!isdigit(ch)) w|=ch==‘-‘,ch=getchar();
12     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
13     x=w?-x:x;
14 }
15
16 int find(int x)
17 {
18     int l=1,r=len,mid;
19     while(l<=r)
20     {
21         mid=(l+r)>>1;
22         if(x>g[mid]) l=mid+1;
23         else r=mid-1;
24     }
25     return l;
26 }
27
28 int main()
29 {
30     rd(n);
31     memset(g,inf,sizeof(g));
32     for(rg int i=1;i<=n;++i) rd(a[i]),ca[a[i]]=i;
33     for(rg int i=1;i<=n;++i) rd(b[i]),cb[i]=ca[b[i]];
34     for(rg int i=1;i<=n;++i)
35     {
36         int k=find(cb[i]);
37         g[k]=cb[i];
38         len=max(len,k);
39     }
40     printf("%d",len);
41     return 0;
42 } 

100昏 手写二分

原文地址:https://www.cnblogs.com/lxyyyy/p/10804386.html

时间: 2024-08-06 07:02:50

【luogu1439】 【模板】最长公共子序列 [动态规划][LIS最长上升子序列][离散化]的相关文章

最长递归子序列、最长公共字串、最长公共子序列、编辑距离

[TOC]   ### 最长递归子序列 #### 题目 给定数组arr,返回arr中的最长递增子序列,如`arr=[2,1,5,3,6,4,8,9,7]`,返回的最长递增子序列为`[1,3,4,8,9]` #### 题解思路 先用DP来求解子序列递增的最大长度,如arr的长度序列为`dp=[1,1,2,2,3,3,4,5,4]`,然后对这个长度序列dp从右到左遍历,得到最长递增子序列. 1. 求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0...i]中的最大递增子序列

算法设计 - LCS 最长公共子序列&amp;&amp;最长公共子串 &amp;&amp;LIS 最长递增子序列

出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的最长公共子串方法.最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^2)的空间复杂度:还可以进一步优化,用后缀数组的方法优化成线性时间O(nlogn):空间也可以用其他方法优化成线性.3.LIS(最长递增序列)DP方法可实现O(n^2)的时间复杂度,进一步优化最佳可达到O(nlogn)

最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和

参考:http://www.ahathinking.com/archives/124.html 最长公共子序列 1.动态规划解决过程 1)描述一个最长公共子序列 如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列.如果序列比较长,这种方法需要指数级时间,不切实际. LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1.z2.……,zk}为X和Y的任意一个LCS,则: (1)如果xm=

动态规划求解最长递增子序列的长度

一,问题描述 给定一个序列,求解它的最长 递增 子序列 的长度.比如: arr[] = {3,1,4,1,5,9,2,6,5}   的最长递增子序列长度为4.即为:1,4,5,9 二,算法分析 有两种方式来求解,一种是转化为LCS问题.即,首先对数组排序,将排序后的结果存储在辅助数组中.排序时间复杂度O(NlogN),排序后的数组与原数组组成了LCS(N,N)问题.解决LCS问题的时间复杂度为O(N^2),故整个算法的时间复杂度为O(N^2),空间复杂度为O(N) 另一种方式是直接用DP求解,算

(最长公共子序列+推导)Love Calculator (lightOJ 1013)

http://www.lightoj.com/volume_showproblem.php?problem=1013 Yes, you are developing a 'Love calculator'. The software would be quite complex such that nobody could crack the exact behavior of the software. So, given two names your software will genera

newcoder 练习赛17 B 好位置 dp 最长公共子序列

链接:https://www.nowcoder.com/acm/contest/109/B来源:牛客网 好位置 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 给出两个串s和x 定义s中的某一位i为好的位置,当且仅当存在s的子序列 满足y=x且存在j使得i=kj成立. 问s中是否所有的位置都是好的位置. 输入描述: 一行两个字符串s,x,这两个串均由小写字母构成.1 <= |s|, |x|

动态规划模板1|LIS最长上升子序列

LIS最长上升子序列 dp[i]保存的是当前到下标为止的最长上升子序列的长度. 模板代码: int dp[MAX_N], a[MAX_N], n; int ans = 0; // 保存最大值 for (int i = 1; i <= n; ++i) { dp[i] = 1; for (int j = 1; j < i; ++j) { if (a[j] < a[i]) { dp[i] = max(dp[i], dp[j] + 1); } } ans = max(ans, dp[i]); }

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

闭关修炼 动态规划1——最长公共子序列(UVA111)

经典算法题每日演练——第四题 最长公共子序列 (来自于转载:http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html) 一: 作用 最长公共子序列的问题常用于解决字符串的相似度,是一个非常实用的算法,作为码农,此算法是我们的必备基本功. 二:概念 举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出 子序列不见得一定是连续的,连续的那是子串. 我想