Codevs 2188 最长上升子序列 - 序列DP

Posted dprswdr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codevs 2188 最长上升子序列 - 序列DP相关的知识,希望对你有一定的参考价值。

传送门

题目描述 Description

LIS问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?

    给出一个长度为N整数序列,请求出它的包含第K个元素的最长上升子序列。

    例如:对于长度为6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。

输入描述 Input Description

第一行为两个整数N,K,如上所述。

    接下来是N个整数,描述一个序列。

 

输出描述 Output Description

请输出两个整数,即包含第K个元素的最长上升子序列长度。

样例输入 Sample Input

8 6

65 158 170 299 300 155 207 389

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

80%的数据,满足0<n<=1000,0<k<=n

100%的数据,满足0<n<=200000,0<k<=n

思路:

本题要求包含第K个元素的最长上升子序列长度,因此最长上升子序列长度dp[n]必须由dp[k]转移来。

AC Code:

80分 O(n^2)做法

#include<cstdio>
#include<algorithm>
using namespace std;
const int sz=200000+10;
int a[sz];
int dp[sz];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int ans=-99;
    for(int i=1;i<=n;i++)
    {
        dp[i]=1;
        for(int j=1;j<i;j++)
        {
            if(a[j]<a[i])
            {
                if(j<k&&a[j]<a[k])
                    dp[i]=max(dp[i],dp[j]+1);
                else if(j==k)
                    dp[i]+=1;
                else if(j>k&&a[j]>a[k])
                    dp[i]=max(dp[i],dp[j]+1);
            }    
        }
        ans=max(ans,dp[i]);
    }
    printf("%d",ans);
    return 0;
}

100分 O(nlogn)做法

 

 

 

 

 

 

以上是关于Codevs 2188 最长上升子序列 - 序列DP的主要内容,如果未能解决你的问题,请参考以下文章

[CODE[VS]] P2188 最长上升子序列

[codevs2185]最长公共上升子序列

最长公共上升子序列(codevs 2185)

codevs 1576 最长严格上升子序列

Codevs 1576 最长严格上升子序列

codevs 1576最长严格上升子序列