poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)

左边的数字是1 2 3 4 5.... 右边的数字 第一个输入的和1连 第2个输入的和2连 右边再按从小到大排序 要求连线不能交叉 问最多能有多少条不交叉的线

假如右边有5个1 那么答案会是5 所以是最大非降子序列

Sample Input
4 //T
6 //n
4
2
6
3
1
5

Sample Output

3

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 # include <cmath>
 6 # define LL long long
 7 using namespace std ;
 8
 9 int a[40010] ;
10 int f[40010] ;
11 //int dp[100010] ;
12 int n ;
13
14 int bsearch(int size, const int &a) {
15     int l=0, r=size-1;
16     while( l <= r ){
17         int mid = (l+r)/2;
18         if( a >= f[mid-1] && a < f[mid] ) return mid;// >&&<= 换为: >= && <
19         else if( a < f[mid] ) r = mid-1;
20         else l = mid+1;
21     }
22 }
23
24 int LIS()
25 {
26     int i, j, size = 1;
27     f[0] = a[0];
28   //  dp[0] = 1;
29     for( i=1; i < n; ++i )
30     {
31         if( a[i] < f[0] ) j = 0; // <= 换为: <
32         else if( a[i] >= f[size-1] ) j = size++;// > 换为: >=
33         else j = bsearch(size, a[i]);
34         f[j] = a[i];
35       //  dp[i] = j+1;
36     }
37
38     return size;
39 }
40
41
42 int main ()
43 {
44    // freopen("in.txt","r",stdin) ;
45     int T ;
46     scanf("%d" , &T) ;
47     while(T--)
48     {
49         int i ;
50         scanf("%d" , &n) ;
51         for (i = 0; i < n ; i++)
52             scanf("%d" , &a[i]) ;
53         printf("%d\n" , LIS()) ; // 求最大递增/上升子序列(如果为最大非降子序列,只需把上面的注释部分给与替换)
54     }
55
56
57     return 0 ;
58 }

时间: 2024-08-27 03:40:19

poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)的相关文章

hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)

题目大意有2n个城市,其中有n个富有的城市,n个贫穷的城市,其中富有的城市只在一种资源富有,且富有的城市之间富有的资源都不相同,贫穷的城市只有一种资源贫穷,且各不相同,现在给出一部分贫穷城市的需求,每个需求都是一个贫穷的向一个富有的城市要资源,且每个富有的城市都想向贫穷的城市输入自己富有的那部分资源,现在为了运输要建设多条路,但是路与路之间不允许有交叉,求满足贫穷城市的各种要求最多可以建设多少条路 简化版::上面n个点,下面n个点,然后在这2n个点之间随意连线,一个点只能被连一次,问最多有多少条

POJ 1631(最长上升子序列 nlogn).

~~~~ 由题意可知,因为左边是按1~n的顺序递增排列,要想得到不相交组合,左边后面的一定与相应右边后面的相连,如此一来, 就可以发现其实是一道最长上升子序列的题目,要注意的是N<40000,用n^2的算法一定会超时. 题目链接:http://poj.org/problem?id=1631 ~~~~ nlogn的算法在这里补充一下. 最长不下降子序列的O(nlogn)算法分析如下: 设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设F [t]

poj 2533 &amp; poj 1631 Longest Ordered Subsequence( LIS果题 )

题目链接: POJ 2533:http://poj.org/problem?id=2533 POJ 1631:http://poj.org/problem?id=1631 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1,

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+二分)

题目链接:POJ 1631 Bridging signals [题意]简单来说就是求最长上升子序列的长度. [思路]这道题目的数据规模有40000之多,如果用普通的动态规划O(n^2)肯定会超时的,所以要用上二分查找(又是二分啊,真牛逼)来进行优化,O(nlogn)的时间复杂度就OK了. 我使用了C++的lower_bound(ForwardIter first, ForwardIter last, const _Tp& val)函数.可以直接查找非递减序列[first, last)中的第一个大

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[

Oracle实现分页,每页有多少条记录数

分页一直都是关系数据库的热门,在数据量非常多的情况下,需要根据分页展示,每页展示多少条记录,以此减轻数据的压力; 1实现原理,根据rownum取记录数,根据公式(页数-1)*每页想要展示的记录数 AND 页数*记录数,其中页数是变量,记录数是常量,ROWNUM为过滤字段. 下面的SQL实现了按页数去查记录,以及规定每页有多少条记录数: SELECT T.* FROM(SELECT ROWNUM AS RN,表名.* FROM 表名) TWHERE RN BETWEEN (页数-1)*记录数+1

POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)

Frogger Time Limit: 1000MS Memory Limit: 65536K Description Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tou

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include <algorithm> #define LEN 10000 using namespace std; struct Node { int left; int right; int count;//被覆盖次数 //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2