计蒜客 最长不下降子序列 (贪心+二分nlogn算法)

Posted vampire6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 最长不下降子序列 (贪心+二分nlogn算法)相关的知识,希望对你有一定的参考价值。

最长不下降子序列

题目链接:https://nanti.jisuanke.com/t/248

题目:

求最长不下降子序列的长度

第一行为n,表示n个数 第二行n个数

最长不下降子序列的长度

N小于5000 for  each  num  < =maxint

样例输入

3
1 2 3

样例输出

3
思路:可以用O(n*n)做,就刚学贪心+二分nlogn的做法,所以这里就试了一下nlogn做法,即采用lower_bound,维护单调数组,
对于序列 a(1, 7, 3, 5, 9, 4, 8),dp的变化过程如下:
  • dp[0] = a[0] = 1,长度为1的LIS结尾元素的最小值自然没得挑,就是第一个数。 (dp = 1)
  • 对于a[1]=7,a[1]>dp[0],因此直接添加到dp尾,dp[1]=a[1]。(dp = 1, 7)
  • 对于a[2]=3,dp[0]< a[2]< dp[1],因此a[2]替换dp[1],令dp[1]=a[2],因为长度为2的LIS,结尾元素自然是3好过于7,因为越小这样有利于后续添加新元素。 (dp = 1, 3)
  • 对于a[3]=5,a[3]>dp[1],因此直接添加到dp尾,dp[2]=a[3]。 (dp = 1, 3, 5)
  • 对于a[4]=9,a[4]>dp[2],因此同样直接添加到dp尾,dp[3]=a[9]。 (dp = 1, 3, 5, 9)
  • 对于a[5]=4,dp[1]< a[5]< dp[2],因此a[5]替换值为5的dp[2],因此长度为3的LIS,结尾元素为4会比5好,越小越好嘛。(dp = 1, 3, 4, 9)
  • 对于a[6]=8,dp[2]< a[6]< dp[3],同理a[6]替换值为9的dp[3],道理你懂。 (dp = 1, 3, 4, 8)
这样子dp数组就维护完毕,所求LIS长度就是dp数组长度4。 
AC代码如下:

//
// Created by hanyu on 2019/8/9.
//
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include<math.h>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1000+7;
#define MAX 0x3f3f3f3f
int main()

    int a[maxn],dp[maxn];
    int n;
    while(~scanf("%d",&n))
    
        memset(a,0,sizeof(a));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++)
        
            scanf("%d",&a[i]);
            dp[i]=MAX;//dp初始化最大值
        
        int pos=0;//dp数组最后一位下标
        dp[0]=a[0];
        
        for(int i=1;i<n;i++)
        
            if(a[i]>=dp[pos])
                dp[++pos]=a[i];
            else
                dp[lower_bound(dp,dp+pos+1,a[i])-dp]=a[i];
        
        printf("%d\n",pos+1);
    
    return 0;

 



以上是关于计蒜客 最长不下降子序列 (贪心+二分nlogn算法)的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客课程竞赛入门--最长上升子序列(LIS) 流程记

计蒜客 17412 Card Hand Sorting 最长公共子序列

模板最长不下降子序列

最长不下降子序列nlogn算法详解

最长不下降子序列 nlogn && 输出序列

最长不下降子序列 (O(nlogn)算法)