http://soj.sysu.edu.cn/show_problem.php?pid=1000&cid=1762
这题的n达到了1000000,n^2的最长递增子序列做法肯定超时,于是有一种二分的算法,与此题完美地结合起来!达到nlogn的时间复杂度!
1 /* 2 最长递增子序列+二分查找 3 因为在获得最长递增子序列的时候,dp数组是有序的,所以把数加进去的时候,就合理地可以用二分啦! 4 5 a: 1 7 3 5 9 4 8 6 dp: 0 0 0 0 0 0 0 0 7 8 a: 1 7 3 5 9 4 8 9 dp: 0 1 0 0 0 0 0 0 (初始化:dp[1] = a[0],下标从1开始,代表最长递增子序列的长度) 10 11 a: 1 7 3 5 9 4 8 12 dp: 0 1 7 0 0 0 0 0 (7找不到比他小的,补在后面) 13 14 a: 1 7 3 5 9 4 8 15 dp: 0 1 3 0 0 0 0 0 (3找到7且小于它,替换之) 16 17 ......到最后...... 18 19 a: 1 7 3 5 9 4 8 20 dp: 0 1 3 4 8 0 0 0 (此时长度为4,最后刚好是8) 21 22 */ 23 24 #include <iostream> 25 #include <cstring> 26 #include <cstdio> 27 28 using namespace std; 29 30 int a[1000005]; 31 int dp[1000005]; 32 33 int binary_search(int l, int r, int key) 34 { 35 if(dp[r] <= key) 36 return r+1; 37 while(l < r) //不能等于啊 38 { 39 int mid = (l + r) / 2; 40 if(dp[mid] <= key) 41 l = mid + 1; 42 else 43 r = mid; 44 } 45 return l; 46 } 47 48 int LIS(int n) 49 { 50 memset(dp, 0, sizeof(dp)); 51 int len = 1; 52 dp[1] = a[0]; 53 for(int i=1; i<n; i++) 54 { 55 int pos = binary_search(1, len, a[i]); 56 dp[pos] = a[i]; 57 if(len < pos) 58 len = pos; 59 } 60 return len; 61 } 62 63 int main() 64 { 65 int n; 66 while(scanf("%d", &n) != EOF) 67 { 68 for(int i=0; i<n; i++) 69 scanf("%d", &a[i]); 70 int len = LIS(n); 71 printf("%d ", len); 72 printf("%d\n", dp[len]); 73 } 74 return 0; 75 }
时间: 2024-10-10 13:01:50