POJ 1631 Bridging signals(LIS+二分)
题目链接:POJ 1631 Bridging signals
【题意】简单来说就是求最长上升子序列的长度。
【思路】这道题目的数据规模有40000之多,如果用普通的动态规划O(n^2)肯定会超时的,所以要用上二分查找(又是二分啊,真牛逼)来进行优化,O(nlogn)的时间复杂度就OK了。
我使用了C++的lower_bound(ForwardIter first, ForwardIter last, const _Tp& val)函数.可以直接查找非递减序列[first, last)中的第一个大于等于值val的位置。
下面贴AC代码:
1 /* 2 ** POJ 1631 Bridging signals 3 ** Created by Rayn @@ 2014/05/06 4 ** 最长上升子序列 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <algorithm> 9 using namespace std; 10 const int MAX = 40010; 11 12 int ans, arr[MAX], dp[MAX]; 13 14 int main() 15 { 16 #ifdef _Rayn 17 freopen("in.txt", "r", stdin); 18 #endif 19 20 int t, n; 21 22 scanf("%d", &t); 23 while(t--) 24 { 25 scanf("%d", &n); 26 for(int i=1; i<=n; ++i) 27 scanf("%d", &arr[i]); 28 29 memset(dp, 0, sizeof(dp)); 30 ans = 0; 31 dp[ans++] = arr[1]; 32 for(int i=2; i<=n; ++i) 33 { 34 if(arr[i] > dp[ans-1]) 35 { 36 dp[ans++] = arr[i]; 37 } 38 else 39 { 40 int *p = lower_bound(dp, dp+ans, arr[i]); 41 *p = arr[i]; 42 } 43 } 44 printf("%d\n", ans); 45 } 46 return 0; 47 }