dp总结day5之最长上升子序列

3 篇文章 0 订阅

首先有一道基础题:最长不下降子序列。(先考虑只求长度)

然而这显然是一道dp题目。

当然有一个比较暴力的n^2求法:

首先用dp[i]表示i位置及以前的最长不下降子序列的长度。

让后枚举1-i中的a[j]

之后就有这样的转移方程dp[i]=max(dp[i-1],dp[j]+1);(仔细想一下就懂了)

然后发现其实有一个究极精简的nlogn的算法:

中间有这样的两个函数:(upper_bound(),lower_bound())

upper_bound返回的是被查序列中第一个大于查找值的指针,也就是返回指向被查值>查找值的最小指针。(摘自网络)

lower_bound返回的是被查序列中第一个大于等于查找值的指针,也就是返回指向被查值>=查找值的最小指针。(摘自网络)

下面先给出程序:

#include<bits/stdc++.h>
using namespace std;
const int mm=100010;
int f[mm];
int n;
int x;
int main()
{
    scanf("%d",&n);
    memset(f,0x3f,sizeof(f));
    for(int i=0;i<n;i++)
    {
        scanf("%d",&x);
        *upper_bound(f,f+n,x)=x;
    }
    printf("%d",lower_bound(f,f+n,0x3f3f3f3f)-f);
    return 0;
}

这是一种贪心的思路:

1.先把f数组赋值INF。

2.每插入一个数x,把前面所有f[i]中第一个大于x的数赋值成x。

3.一波之后,运用lower_bound找出f数组中小于INF的所有数的个数(全部集中在前面),输出就可以求出个数。

考虑一下求出整个数列是多少:

然而,nlogn的算法是求不出这个最长不下降子序列是什么的(思考一下,为什么不行),n^2算法是可以求出的:加一个pre[]数组在每次更新时,记录不下降子序列的前一项是多少,最后利用pre[]推导出整个数列。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值