The Longest Increasing Subsequence (LIS)

传送门

十分重要的基础DP问题,是学习用各种方式优化DP的一个很好的例子。

设DP[i]表示以a[i]结尾的LIS的长度,则状态转移方程为

DP[1]=1

DP[i] = max{DP[j], j<i && a[j]<a[i]} + 1, i>1

暴力求解复杂度为O(N^2)。

优化1

考虑函数f(L):长度为 L 的 Increasing Sequence (IS) 的最小结尾, 显然f(L)是单调递增的。

从左到右扫描数组,维护动态的f(L)。

再看上面的DP方程,考虑我们维护的这个函数f(L)如何加速DP状态转移时所需的查询。

显然我们以a[i]为key,二分查询f(L),得到max{L, f(L)<a[i]}

复杂度降为O(N*logN)

这一类DP优化方法可归纳为 加速DP Query

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_N=1e6+10, oo=1e6;
int A[MAX_N], f[MAX_N];
//二分法: binary_search(y, f())
//设有一个单调(不要求严格单调)的函数f()
//可以在O(log N)的时间内求解以下问题:
//给定y,求满足f(x)<=y/f(x)>=y的最大/最小的x
//

int binary_search(int y, int l, int r){ //y is the key
  int mid;
  while(r-l>1){ //r is illegal
    mid=(l+r)>>1;
    if(f[mid]<y){
      l=mid;
    }
    else r=mid;
  }
  return l;
}

int main(){
  //freopen("in", "r", stdin);
  int N, ans=0;
  scanf("%d", &N);
  for(int i=1; i<=N; i++) scanf("%d", A+i);

  f[0]=0;
  for(int i=1; i<=N; i++) f[i]=oo;
  for(int i=1; i<=N; i++){
    int tmp=binary_search(A[i], 0, ans+1)+1;
    ans=max(ans, tmp);
    f[tmp]=min(f[tmp], A[i]);
  }
  printf("%d\n", ans);
  return 0;
}

优化2

时间: 2024-10-10 16:43:05

The Longest Increasing Subsequence (LIS)的相关文章

LintCode Longest Increasing Subsequence

Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return the length of the LIS. Clarification What's the definition of longest increasing subsequence? The longest increasing subsequence problem is to find a

Longest Increasing Subsequence

Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&&a[j]<a[i]}+1 直接两个for [二分查找优化]:O(n^2) g(i):d值为i的最小的a  每次更新然后lower_bound即可 [大于等于] lower_boundReturn iterator to lower bound Returns an iterator pointing

LintCode刷题笔记--Longest Increasing Subsequence

动态规划 描述: Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return the length of the LIS. Clarification What's the definition of longest increasing subsequence? The longest increasing subsequence problem is t

[LintCode]76. Longest Increasing Subsequence

Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return the length of the LIS. Example For [5, 4, 1, 2, 3], the LIS is [1, 2, 3], return 3 For [4, 2, 4, 5, 3, 7], the LIS is [2, 4, 5, 7], return 4 Challenge

DP(dynamic programming)之LIS(longest increasing subsequence)问题(转)

今天回顾WOJ1398,发现了这个当时没有理解透彻的算法.看了好久好久,现在终于想明白了.试着把它写下来,让自己更明白. 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS.排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5.下面一步一步试着找出它.我们定义一个序列B,然后令 i = 1 to 9 逐个考察这个序列.此外,我们用一个变

300. Longest Increasing Subsequence

Problem statement: Given an unsorted array of integers, find the length of longest increasing subsequence. For example,Given [10, 9, 2, 5, 3, 7, 101, 18],The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there

Dynamic Programming | Set 3 (Longest Increasing Subsequence)

在 Dynamic Programming | Set 1 (Overlapping Subproblems Property) 和 Dynamic Programming | Set 2 (Optimal Substructure Property) 中我们已经讨论了重叠子问题和最优子结构性质,现在我们来看一个可以使用动态规划来解决的问题:最长上升子序列(Longest Increasing Subsequence(LIS)). 最长上升子序列问题,致力于在一个给定的序列中找到一个最长的子序列

[LeetCode][JavaScript]Longest Increasing Subsequence

Longest Increasing Subsequence Given an unsorted array of integers, find the length of longest increasing subsequence. For example,Given [10, 9, 2, 5, 3, 7, 101, 18],The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Not

LeetCode 300. Longest Increasing Subsequence

300. Longest Increasing Subsequence Description Submission Solutions Add to List Total Accepted: 64115 Total Submissions: 170859 Difficulty: Medium Contributors: Admin Given an unsorted array of integers, find the length of longest increasing subsequ