hdu 1950 Bridging signals

链接

[http://acm.hdu.edu.cn/showproblem.php?pid=1950]

题意

LIS

分析

因为一般那个dp是n^2的所以会超时
必须用那个nlogn的。
大佬链接
[https://blog.csdn.net/shuangde800/article/details/7474903]
这个地方就是用一个数组记录
d[len]表示到当前长度为len的可能有很多个,你就记录末尾那个数最小的。
最长上升子序列(LIS)的典型变形,熟悉的n^2的动归会超时。LIS问题可以优化为nlogn的算法。
定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素。
注意d中元素是单调递增的,下面要用到这个性质。
首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];
否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],则根据D的定义,我们需要更新长度为j的上升子序列的最末元素(使之为最小的)即 d[j] = a[i];
最终答案就是len
利用d的单调性,在查找j的时候可以二分查找,从而时间复杂度为nlogn。

代码

/*
    HDU 1950 Bridging signals
            -----最长上升子序列nlogn算法
*/
 
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 40005
int arr[MAXN],ans[MAXN],len;

int main()
{
  //freopen("in.txt","r",stdin);
    int T,p,i,j,k;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&p);
        for(i=1; i<=p; ++i)
            scanf("%d",&arr[i]);
        
        ans[1] = arr[1];
        len=1;
        for(i=2; i<=p; ++i)
            if(arr[i]>ans[len])
                ans[++len]=arr[i];
            else{
                int pos=lower_bound(ans,ans+len,arr[i])-ans;   
                ans[pos] = arr[i];
        }
        printf("%d\n",len);
    }
    return 0;
}

转载于:https://www.cnblogs.com/mch5201314/p/10622322.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值