最长上升子序列

来源:互联网 发布:搜房帮网络经纪人登录 编辑:程序博客网 时间:2024/06/08 14:01

问题描述 Problem 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

对于所有的数据,满足 0<n2000000<kn


分析 I Think

求包含 K 的最长上升子序列,只需要把第 K 个元素之前大于第 K 个元素和第 K 个元素之后小于第 K 个元素的元素删除,再求最长上升子序列就可以了


代码 Code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int f[200001];int a[200001];int b[200001];int n,m;int lis(int,int);int binary(int,int,int);int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i)        scanf("%d",&a[i]);    for(int i=1;i<m;++i)        if(a[i] <= a[m])            b[++b[0]] = a[i];    b[++b[0]] = a[m];    for(int i=1+m;i<=n;++i)        if(a[i] >= a[m])            b[++b[0]] = a[i];    printf("%d\n",lis(1,b[0]));    return 0;}int lis(int L,int R){    f[f[0]=1] = b[L];    for(int i=L+1;i<=R;++i){        if(b[i] > f[f[0]])            f[++f[0]] = b[i];        else if(f[1] > b[i])            f[1] = b[i];        else            f[binary(1,f[0],b[i])] = b[i];    }    return f[0];}int binary(int L,int R,int N){    int M;    while(L+1 < R){        M = (L+R)>>1;        if(f[M] == N)            return M;        if(f[M] > N)            R = M;        else            L = M;    }    if(f[L] > N)        return L;    return R;}
0 0
原创粉丝点击