sicily LIS

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 }

 

posted @ 2015-03-29 11:53  dominjune  阅读(206)  评论(0编辑  收藏  举报