dp最长递增子序列的nlogn算法实现

n2的算法很简单,这里是利用另外一个数组d,d[i]存的是长度为i的最末尾元素。因为d[i]是有序的,可以用二分查找优化,复杂度降低为nlogn,代码如下,注意二分查找的边界:

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
const int N = 41000;  
int a[N];       //a[i] 原始数据  
int d[N];       //d[i] 长度为i的递增子序列的最小值  
  
int BinSearch(int key, int* d, int low, int high)  
{  
    while(low<=high)  
    {  
        int mid = (low+high)>>1;  
        if(key>d[mid] && key<=d[mid+1])  
            return mid;  
        else if(key>d[mid])  
            low = mid+1;  
        else  
            high = mid-1;  
    }  
    return 0;  
}  
  
int LIS(int* a, int n, int* d)  
{  
    int i,j;  
    d[1] = a[1];  
    int len = 1;        //递增子序列长度  
    for(i = 2; i <= n; i++)  
    {  
        if(d[len]<a[i])  
            j = ++len;  
        else  
            j = BinSearch(a[i],d,1,len) + 1;  
        d[j] = a[i];  
    }  
    return len;  
}  
  
int main()  
{  
    int t;  
    int p;  
    scanf("%d",&t);  
    while(t--)  
    {  
        scanf("%d",&p);  
        for(int i = 1; i <= p; i++)  
            scanf("%d",&a[i]);  
        printf("%d\n",LIS(a,p,d));  
    }  
    return 0;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值