洛谷 P1439 模板最长公共子序列
Posted 俺是小程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1439 模板最长公共子序列相关的知识,希望对你有一定的参考价值。
神TM模板。。我本来想休闲一下写点水题的。。。
开始做的时候直接敲了一个O(N2)的算法上去,编译的时候才发现根本开不下。。
好了,谈回这道题。
先不加证明的给出一种算法。
若有一组数据 2 4 2 5 1 3 2 5 4 1 3 那么我们令 4 2 5 1 3 | | | | | 1 2 3 4 5 第三行的数据就变成 2 3 1 4 5 很明显,答案是这个数据的最长上升子序列,即4 == 2 3 4 5,即原数列的2 5 1 3。
现在来大概的介绍一下这样做的原因。
首先,观察题目,注意到这个题和真正的模板的区别:给出1-n的两个排列P1和P2。
思考排列的性质,及从1-N的每个数会且仅会出现一次。
引用洛谷题解中一句话,因为最长公共子序列是按位向后比对的,所以a序列每个元素在b序列中的位置如果递增,就说明b中的这个数在a中的这个数整体位置偏后,可以考虑纳入LCS——那么就可以转变成nlogn求用来记录新的位置的map数组中的LIS。
于是即可写出代码。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAXN = 1e5 + 20; 4 const int INF = 0x3f3f3f3f; 5 6 inline int read() 7 { 8 int x = 0; char ch = getchar(); 9 while(!isdigit(ch)) ch = getchar(); 10 while(isdigit(ch)) x = x * 10 + ch - ‘0‘, ch = getchar(); 11 return x; 12 } 13 14 int N; 15 int a[MAXN], f[MAXN]; 16 17 int main() 18 { 19 cin>>N; 20 for(int i = 1; i <= N; i++) 21 a[read()] = i; 22 23 memset(f, 0x3f, sizeof(f)); 24 int cur; 25 for(int i = 1; i <= N; i++) 26 { 27 cur = a[read()]; 28 *lower_bound(f, f + N + 1, cur) = cur; 29 } 30 31 cout<<(lower_bound(f, f + N + 1, INF) - f)<<endl; 32 return 0; 33 }
以上是关于洛谷 P1439 模板最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章