poj 1631 Bridging signals (LIS 之 n×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)/2;
    }
    return l;
}
int main()
{
    int a[40005],T,i,j,len;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(i=0;i<=n;i++)  
            c[i]=INT_MAX;
        c[0]=-1;
        c[1]=a[0];
        len=1;
        for(i=1;i<n;i++){
            j=bin_find(a[i]);
            c[j]=a[i];
            if(j>len)
                len=j;
        }
        printf("%d\n",len);
    }
    return 0;
}

顺便研究了下这个算法打印路径的写法,通过逆序循环,仅供参考

void path()
{
    int i,j,k=len;
    for(i=n-1;i>=1;i--){
        j=bin_find(a[i]);
        if(j==k)
            b[k--]=i+1;
    }
    for(i=0;i<b[2]-1;i++)
        if(a[i]<a[b[2]-1]){
            b[1]=i+1;
            break;
        }
    for(i=1;i<len;i++)
        printf("%d ",b[i]);
    printf("%d\n",b[len]);
}
				
时间: 2024-10-26 02:03:18

poj 1631 Bridging signals (LIS 之 n×logn  算法)的相关文章

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

题目链接: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 &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

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

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] 显然,我们在查找时便可以利用二分搜索,从而把复杂度从原来的

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]