题目大意: 左边有一列数(n个),右边有一列数(也是n个),左边的某个数和右边的某个数用一条线相连(一共n条线)。请问这些线互不相交的最大条数是多少?
输入的格式: t(有t个测试例子) n1(有n1个数) x1 x2 x3 ....xn (代表右列的数字);表示右边数列这个数x1要与左列的1相连,数x2要和左列的2相连;
比如 n=6 x1=4 x2=2 x3=6 x4=3 x5=1 x6=5 ,即是右列的4跟左列的1相连.....描述的就跟题目给出的图形一样。
因为 已经保证了左列1 <2<3<4<5<6, 如果要让x1 和 1 以及 x2和2的连线不相交,则x1要保证小于x2 , 所以也就是求最长递增自序列的问题!
题目数据量较大,要用优化后的最长递增自序列算法。
O(n*logn)最长递增自序列: http://www.cnblogs.com/lonelycatcher/archive/2011/07/28/2119123.html
//用常规顺序搜索会超时,要改用用二分,(注意长度len为0时即b[0]的初始设置).
//求最长递增时 b[0]=min_inf(比题目最小值还要小的值) 求最长递减时 b[0]=max_inf(比题目最大值还要大的值)
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int p;
scanf("%d",&p);
int len=1;
int b[40010]={0,p};//b[0]=0 比题目给的最小值1还要小的值
for(int i=2;i<=n;i++)
{
scanf("%d",&p);
int l=0;
int r=len;
while(l<=r)
{
int m = (l+r)/2;
if(b[m]<p) {
l=m+1;
}else{
r=m-1;
}
}
b[l]=p;
if(l>len){
len++;
}
}
printf("%d\n",len);
}
return 0;
}
本文介绍了一种解决最长递增子序列问题的高效算法,采用二分查找优化,复杂度为O(n*logn)。适用于求解连线不相交的最大数量问题,通过实例解析算法实现过程。
6万+

被折叠的 条评论
为什么被折叠?



