洛谷 P1439 【模板】最長公共子序列
阿新 • • 發佈:2018-04-30
clu () 休閑 一句話 中一 AD DC == c++
神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; charch = 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 【模板】最長公共子序列