zoukankan      html  css  js  c++  java
  • codevs 2188 最长上升子序列

    题目描述 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个元素。稍微进行一下修改即可。

            当查找的第k个元素时,由于必须包含k,所以k插入位置x即为此时找到的最长上升子序列的长度。因为f数组中f[x]以后的数都是在k之前出现的比k大的数。此是f[1]~f[x]为一固定的序列,不再发生变化。然后a数组往后查找时,若有比a[k]小的数,直接忽略不进行运算。就避免了f[1]~f[k]序列中的数发生变化。

    #include<cstdio>
    #include<iostream>
    #define N  200100
    using namespace std;
    int n,k,len=1,l=0;
    int a[N];
    int f[N];
    int erfen(int l,int r,int p)
    {
        if (l>r) return l;
        int mid=(l+r)>>1;
        if (f[mid]<p) erfen(mid+1,r,p);
          else erfen(l,mid-1,p);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        f[len]=a[1];
        for (int i=2;i<=n;i++)
          {
               if (i>k&&a[i]<a[k]) continue;//忽略比a[k]小的数 
               int bj;
               if (a[i]>f[len]) f[++len]=a[i],bj=len;
               else 
                 bj=erfen(l,len,a[i]);
               if (bj>len) len=bj;
               f[bj]=a[i];
               if (i==k) l=len=bj;//长度进行更改 
          }
        printf("%d",len);
        return 0;
    }
    必须包含第k个元素
  • 相关阅读:
    DOM深度优先遍历算法
    DOM事件
    DOM修改
    DOM的方法和属性
    DOM简介
    JSON.stringify()
    JSON解析
    JSON对象
    JSON语法
    JSON对比XML
  • 原文地址:https://www.cnblogs.com/sjymj/p/6001184.html
Copyright © 2011-2022 走看看