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 }

时间: 2024-10-04 18:45:26

POJ 1631 Bridging signals(LIS+二分)的相关文章

POJ 1631 Bridging signals(LIS:最长上升子序列)

http://poj.org/problem?id=1631 题意: (题意比较繁琐)本质就是: 给你一个长为n(n<=40000)的整数序列, 要你求出该序列的最长上升子序列LIS. 分析: 如果用O(n^2)的算法的话, 可能会超时. 所以用O(n*logn)的算法. 令g[i]==x表示当前遍历到的长度为i的所有最长上升子序列中的最小序列末尾值为x.(如果到目前为止, 根本不存在长i的上升序列, 那么x==INF无穷大) 假设当前遍历到了第j个值即a[j], 那么先找到g[n]数组的值a[

poj 1631 Bridging signals (LIS 之 n&#215;logn  算法)

链接:poj 1631 题意:没看题的具体意思,本质是求最长升序子序列的长度 #include<stdio.h> #include<limits.h> int c[40005],n; int bin_find(int x) //二分查找 { int l=0,r=n,mid=(l+r)/2; while(l<=r){ if(x>c[mid]) l=mid+1; else if(x<c[mid]) r=mid-1; else return mid; mid=(l+r)

POJ 1631 Bridging signals &amp; 2533 Longest Ordered Subsequence

两个都是最长上升子序列,所以就放一起了 1631 因为长度为40000,所以要用O(nlogn)的算法,其实就是另用一个数组c来存储当前最长子序列每一位的最小值,然后二分查找当前值在其中的位置:如果当前点不能作为当前最长子序列的最大值,则更新找到值为两者间的较小值. 2533 就是一个裸的最长上升子序列...这里就不多说了,直接dp就好... 1611: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio

POJ 1631 Bridging signals(LIS 二分 快速方法)

Language: Default Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10762   Accepted: 5899 Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designers

POJ 1631 Bridging signals(LIS 二分法 高速方法)

Language: Default Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10762   Accepted: 5899 Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designers

POJ - 1631 Bridging signals(最长上升子序列---LIS)

题意:左右各n个端口,已知n组线路,要求切除最少的线路,使剩下的线路各不相交,按照左端口递增的顺序输入. 分析: 1.设左端口为l,右端口为r,因为左端口递增输入,l[i] < l[j](i < j),因此若要不相交,r[i] < r[j],由此可以得出,只要求出对应的右端口序列的最长上升子序列的长度即可. 2.最长上升子序列: dp[i]---长度为i+1的上升子序列中末尾元素的最小值(若不存在,则为INT_INF). 如果子序列长度相同,那么最末位元素较小的在之后会更加有优势. #p

poj 1631 Bridging signals DP(最长上升子序列)

最近一直在做<挑战程序设计竞赛>的练习题,感觉好多经典的题,都值得记录. 题意:给你t组数据,每组数组有n个数字,求每组的最长上升子序列的长度. 思路:由于n最大为40000,所以n*n的复杂度不够了,会超时. 书上状态方程换成了d[i]——以长度为i+1的上升子序列中末尾元素的最小值. 那么我们在遍历第i个元素时候,以这个元素为末尾元素的最长子序列也就是在d[i]中找到一个小于num[i]的最大值,然后在这个序列末尾加上num[i] 显然,我们在查找时便可以利用二分搜索,从而把复杂度从原来的

HDU 1950 Bridging signals(LIS O(nlogn))

Bridging signals Problem Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designers have screwed up completely, making the signals on the chip connecting the ports of two functi

hdoj 1950 Bridging signals【二分求最大上升子序列长度】

Bridging signals Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 961    Accepted Submission(s): 627 Problem Description 'Oh no, they've done it again', cries the chief designer at the Waferland