https://www.51nod.com/tutorial/course.html#!courseId=12

解题关键:

如果将子序列按照长度由短到长排列,将他们的最大元素放在一起,形成新序列$B\left\{ {{b_1},{b_2}, \ldots  \ldots ,{b_j}} \right\}$,则序列$B$满足${b_1} < {b_2} <  \ldots  \ldots  < {b_j}$。这个关系比较容易说明,假设${b_{xy}}$表示序列A中长度为$x$的递增序列中的第$y$个元素,显然,如果在序列$B$中存在元素${b_{mm}} > {b_{nn}}$,且$m < n$则说明子序列${B_n}$的最大元素小于${B_m}$的最大元素,因为序列是严格递增的,所以在递增序列${B_n}$中存在元素${b_{nm}} < {b_{nn}}$,且从${b_{n0}}$到${b_{nm}}$形成了一个新的长度为$m$的递增序列,因为${b_{mm}} > {b_{nn}}$,所以${b_{mm}} > {b_{nm}}$,这就说明在序列$B$中还存在一个长度为$m$,最大元素为${b_{nm}} < {b_{mm}}$的递增子序列,这与序列的定义,${b_{mm}}$是所有长度为m的递增序列中第$m$个元素最小的序列不符,所以序列$B$中的各元素严格递增。

注意liss存的是下标,主要是为了求pre用,若只求max,你当然可以设成值。

爆炸了,刚发现《挑战竞赛程序设计》上有一个代码非常非常简短的模板,炸了;

STL模板:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<functional>
 6 using namespace std;
 7
 8 const int N=131072;
 9 int n=7, a[N] = {0,0,1,1,0,0,2};
10 template<class Cmp>
11 int LIS (Cmp cmp){
12     static int m=0,end[N];
13     for(int i=0;i<n;i++){
14         int pos=lower_bound(end,end+m,a[i],cmp)-end;
15         end[pos]=a[i],m+=pos==m;
16     }
17     return m;
18 }
19 bool greater1(int value){
20     return value>=1;
21 }
22
23 int main(){
24     cout<<LIS(less<int>())<<endl;         //严格上升
25     cout<<LIS(less_equal<int>())<<endl;   //非严格上升
26     cout<<LIS(greater<int>())<<endl;      //严格下降
27     cout<<LIS(greater_equal<int>())<<endl;//非严格下降
28     cout<<count_if(a,a+7,greater1)<<endl; //计数
29     //第二个参数为末尾元素的下一个位置
30     return 0;
31 }  

最终模板:

 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 typedef long long ll;
 5 ll a[50002],dp[50002];
 6 int main(){
 7     int n;
 8     cin>>n;
 9     for(int i=0;i<n;i++){
10         cin>>a[i];
11     }
12     fill(dp,dp+n,INF);
13     for(ll i=0;i<n;i++){
14         *lower_bound(dp,dp+n,a[i])=a[i];
15     }
16     printf("%lld\n",lower_bound(dp,dp+n,INF)-dp);
17 } 

自己改进模板(不带路径):注意二分时上界为len+1就ok了,也可以fill成inf,更简单明了

 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 typedef long long ll;
 5 int arr[50002],dp[50002];
 6 int n,len;
 7 int find1(int x){
 8     int mid,l=1,r=len+1;
 9     while(l<r){
10         mid=(l+r)>>1;
11         if(dp[mid]>x) r=mid;
12         else l=mid+1;
13     }
14     return r;
15 }
16 int lis(){
17     int dex;
18     for(int i=1;i<=n;i++){
19        dex=find1(arr[i]);
20         dp[dex]=arr[i];
21         len=max(len,dex);
22     }
23     return len;
24 }
25 int main(){
26     cin>>n;
27     for(int i=1;i<=n;i++){
28         cin>>arr[i];
29     }
30     ll ans=lis();
31     printf("%lld\n",ans);
32     return 0;
33 }

带路径模板1

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<iostream>
 6 using namespace std;
 7 typedef long long ll;
 8 int a[50002],dp[50002],pre[50002],res[50002],n;
 9 int len;
10
11 int find1(int x){
12     int mid,l=1,r=len+1;
13     while(l<r){
14         mid=(l+r)>>1;
15         if(a[dp[mid]]>x) r=mid;
16         else l=mid+1;
17     }
18     return r;
19 }
20
21 int lis(){
22     len=0;
23     for(int i=1;i<=n;i++){
24         int dex=find1(a[i]);
25         dp[dex]=i;
26         if(dex!=1) pre[i]=dp[dex-1];
27         len=max(len,dex);
28     }
29
30     int k=dp[len],t=len;
31     while(pre[k]!=k){
32         res[t--]=a[k];
33         k=pre[k];
34     }
35     res[t]=a[k];
36     return len;
37 }
38 int main(){
39     cin>>n;
40     for(int i=0;i<=n+2;i++)    pre[i]=i;
41     for(int i=1;i<=n;i++)    cin>>a[i];
42
43     ll ans=lis();
44     printf("%lld\n",ans);
45     for(int i=1;i<=ans;i++){
46         printf("%d ",res[i]);
47     }
48     printf("\n");
49 }

带路径模板2

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<iostream>
 6 using namespace std;
 7 typedef long long ll;
 8 int arr[50002],liss[50002],pre[50002],res[50002];
 9 int find1(int i,int l,int r){
10     int mid;
11     while(l<r){
12         mid=(l+r)>>1;
13         if(arr[liss[mid]]>arr[i]) r=mid;
14         else l=mid+1;
15     }
16     return r;
17 }
18 int lis(int len){
19     int max=1;
20     liss[0]=0;
21     for(int i=0;i<len;i++){
22         int index=find1(i,0, max-1);
23         if(index==0&&arr[liss[index]]>=arr[i]){
24             liss[index]=i;
25             continue;
26         }//增加这条语句主要是pre的影响,不需要路径的话,完全可以去掉。
27         if(index==max-1&&arr[liss[index]]<arr[i]){
28             liss[max++]=i;
29             pre[i]=liss[index];
30             continue;
31         }
32         liss[index]=i;
33         pre[i]=liss[index-1];
34     }
35
36     int k=liss[max-1],t=max-1;
37     while(pre[k]!=k){
38         res[t--]=arr[k];
39         k=pre[k];
40     }
41     res[t]=arr[k];
42     return max;
43 }
44 int main(){
45     int n;
46     cin>>n;
47     for(int i=0;i<n+2;i++){
48         pre[i]=i;
49     }
50     for(int i=0;i<n;i++){
51         cin>>arr[i];
52     }
53     ll ans=lis(n);
54     printf("%lld\n",ans);
55     for(int i=0;i<ans;i++){
56         printf("%d ",res[i]);
57     }
58     printf("\n");
59 }

转载于:https://www.cnblogs.com/elpsycongroo/p/6847444.html

[dp]最长单调递增子序列LIS相关推荐

  1. 最长单调递增子序列 python_最长单调递增子序列

    前面三篇博客分别讲了贪心,递归,分治,今天就说个简单的动态规划(DP)的题目吧.在我心中DP算是比较难的算法,尤其像状态DP,树形DP,因为实力问题就说一个简单的线性DP--最长单调递增子序列. 题目 ...

  2. 最长单调递增子序列O(NlogN)算法

     O(NlgN)算法 假设存在一个序列d[1..9] ={ 2,1 ,5 ,3 ,6,4, 8 ,9, 7},可以看出来它的LIS长度为5.  下面一步一步试着找出它.  我们定义一个序列B,然后 ...

  3. 输出最长单调递增子序列java_动态规划实现最长单调递增子序列

    1. 实验环境 操作系统:Mac 64 运行内存:16GB 编程语言:Java 编译环境:Eclipse 2. 题目要求 设计一个Ο(nlgn)时间的算法,求一个 n 个数的序列的最长单调递增子序列. ...

  4. 动态规划作业 最长单调递增子序列

    动态规划作业 1.最长单调递增子序列 设计一个 O(n2)时间的算法,找出由 n 个数组成的序列 a 的最长单调递增子序列. 提示: 用数组 b[0:n]纪录以 a[i] (0<= i< ...

  5. 最长单调递增子序列(时间复杂度O(nlogn))

    写在前面:仅为个人代码/总结,未必标准,仅供参考!如有错误,还望指出交流,共同进步! 最长单调递增子序列 [题目描述] 找出由n个数组成的序列中的最长单调递增子序列及其长度. [O(n*n)算法解题思 ...

  6. 最长单调递增子序列 动态规划 (java)

    题目描述: 设计一个O(N^2)算法,找出n个数据组成的序列的最长单调递增子序列. 输入示例: 8 1 2 3 -9 3 9 0 11 输出示例: 5 1 2 3 9 11 设计思路: 有一个数组 a ...

  7. 最长单调递增子序列 [转]

    [转] http://skynewborn.blog.sohu.com/66594610.html 单调子序列包含有单调递增子序列和递减子序列,不失一般性,这里只讨论单调递增子序列.首先,从定义上明确 ...

  8. java最长单调递增子序列_最长单调递增子序列问题

    最长单调递增子序列问题 题目:设计一个 O( n ^ 2 )复杂度的算法,找出由 n 个数组成的序列的最长单调递增子序列. import java.util.Scanner; public class ...

  9. 最长单调递增子序列--动态规划

    最长单调递增子序列定义: 问题描述: 设计一个O(n2)时间的算法, 找出由n个数组成的序列的最长单调递增子序列. 输入 第1个整数n(0<n<100),表示后面有n个数据,全部为整数. ...

最新文章

  1. 第一个Servlet和Jsp
  2. 简述java中的注释以及用法_怎样理解 Java 注解和运用注解编程?
  3. Python标准库_ sys,random,time
  4. 傅里叶变换是用来做什么的,具体举例一下应用?
  5. 团队开发框架(Developement Structure for Team),内容列表及整理计划
  6. VB 读写TXT文本文件函数
  7. 卷影副本(Shadow Copies)
  8. 零基础快速学会用spss分析问卷
  9. android开发先学什么,Android开发入门教程应该先学什么
  10. android 涨潮动画加载_潮汐apk客户端-潮汐android最新版APP下载v2.0.1.1 免费版-腾牛安卓网...
  11. docker装LibreELEC_只需一步 树莓派刷入LibreELEC系统变身电视机顶盒
  12. 多重重要性采样(MIS)与光线追踪技术
  13. N-BaIoT-Network-based-Detection-of-IoT-Botnet-Attacks
  14. 3G网络通信技术与4G网络通信技术的区别
  15. java 实现超级玛丽小游戏
  16. 上传附件,附件类型问题
  17. 【Opencv】目标追踪——高斯混合模型分离算法(MOG)
  18. 假如任正非这个“太阳”不在了,华为怎么办?
  19. 基于基站定位数据的商圈分析
  20. 电路习题解答 第五章 5-5、5-6

热门文章

  1. 【ZOJ - 2955】Interesting Dart Game(背包,结论,裴蜀定理,数论)
  2. 【nyoj 270】数的分解(统计因子模板)
  3. Java基础部分快速复习(以前复习的时候放在自己的新浪博客上)
  4. oracle编译失效物化视图,使用“不存在”的Oracle物化视图
  5. apmserver导入MySQL_mysql数据库导入导出
  6. win10一按右键就闪屏_升级Win10正式版后屏幕一直闪烁正确的解决办法
  7. html自定义标记,HTML模板(自定义)标记
  8. php长轮询阻塞,ajax长轮询时php被阻塞
  9. leetcode 152 乘积最大子序列
  10. 在Ubuntu环境下使用vcpkg安装sqlite_orm包文件