标签:
有一定思维难度的题目。。看了mps大爷的题解才会做(%%% mps)
考虑暴力O(n^2)dp的算法,只有当A[i] == B[j]时才会+1。我们可以利用这个性质,记录下每个数在A[i]中的5个位置。然后从前往后扫描B,顺便转移。转移时要维护前缀max,这个可以用树状数组随意维护一下。时间复杂度是O(nlogn)的
具体看代码
1 //F[i]表示B与A中前i个数的LCS长度 2 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 void Get_Val(int &Ret) 9 { 10 Ret = 0; 11 char ch; 12 while (ch = getchar(), ch > ‘9‘ || ch < ‘0‘) 13 ; 14 do 15 { 16 (Ret *= 10) += ch - ‘0‘; 17 } 18 while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘); 19 } 20 21 const int Max_N(20050); 22 23 int N; 24 int A[Max_N * 5], B[Max_N * 5]; 25 int tot[Max_N], g[Max_N][6]; 26 27 int F[Max_N * 5]; 28 int BIT[Max_N * 5]; 29 30 inline 31 int lowbit(const int &x) 32 { 33 return x & -x; 34 } 35 36 void Change(int i, const int &x) 37 { 38 while (i <= N * 5) 39 { 40 BIT[i] = max(BIT[i], x); 41 i += lowbit(i); 42 } 43 } 44 45 int Query(int i) 46 { 47 int Ret(0); 48 while (i) 49 { 50 Ret = max(Ret, BIT[i]); 51 i -= lowbit(i); 52 } 53 return Ret; 54 } 55 56 void init() 57 { 58 Get_Val(N); 59 for (int i = 1;i <= N * 5;++i) 60 Get_Val(A[i]), g[A[i]][++tot[A[i]]] = i; 61 for (int i = 1;i <= N * 5;++i) 62 Get_Val(B[i]); 63 } 64 65 void dp() 66 { 67 int k, Ans(0); 68 for (int i = 1;i <= N * 5;++i) 69 for (int p = 5;p >= 1;--p) 70 { 71 k = g[B[i]][p]; 72 Ans = max(Ans, F[k] = Query(k - 1) + 1); 73 Change(k, F[k]); 74 } 75 printf("%d\n", Ans); 76 } 77 78 int main() 79 { 80 init(); 81 dp(); 82 return 0; 83 }
标签:
原文地址:http://www.cnblogs.com/Created-equal/p/5222872.html