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模板:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
using namespace std; const int N=;
int n=, a[N] = {,,,,,,};
template<class Cmp>
int LIS (Cmp cmp){
static int m=,end[N];
for(int i=;i<n;i++){
int pos=lower_bound(end,end+m,a[i],cmp)-end;
end[pos]=a[i],m+=pos==m;
}
return m;
}
bool greater1(int value){
return value>=;
} int main(){
cout<<LIS(less<int>())<<endl; //严格上升
cout<<LIS(less_equal<int>())<<endl; //非严格上升
cout<<LIS(greater<int>())<<endl; //严格下降
cout<<LIS(greater_equal<int>())<<endl;//非严格下降
cout<<count_if(a,a+,greater1)<<endl; //计数
//第二个参数为末尾元素的下一个位置
return ;
}

最终模板:

 #include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll a[],dp[];
int main(){
int n;
cin>>n;
for(int i=;i<n;i++){
cin>>a[i];
}
fill(dp,dp+n,INF);
for(ll i=;i<n;i++){
*lower_bound(dp,dp+n,a[i])=a[i];
}
printf("%lld\n",lower_bound(dp,dp+n,INF)-dp);
}

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

 #include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int arr[],dp[];
int n,len;
int find1(int x){
int mid,l=,r=len+;
while(l<r){
mid=(l+r)>>;
if(dp[mid]>x) r=mid;
else l=mid+;
}
return r;
}
int lis(){
int dex;
for(int i=;i<=n;i++){
dex=find1(arr[i]);
dp[dex]=arr[i];
len=max(len,dex);
}
return len;
}
int main(){
cin>>n;
for(int i=;i<=n;i++){
cin>>arr[i];
}
ll ans=lis();
printf("%lld\n",ans);
return ;
}

带路径模板1

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
using namespace std;
typedef long long ll;
int a[],dp[],pre[],res[],n;
int len; int find1(int x){
int mid,l=,r=len+;
while(l<r){
mid=(l+r)>>;
if(a[dp[mid]]>x) r=mid;
else l=mid+;
}
return r;
} int lis(){
len=;
for(int i=;i<=n;i++){
int dex=find1(a[i]);
dp[dex]=i;
if(dex!=) pre[i]=dp[dex-];
len=max(len,dex);
} int k=dp[len],t=len;
while(pre[k]!=k){
res[t--]=a[k];
k=pre[k];
}
res[t]=a[k];
return len;
}
int main(){
cin>>n;
for(int i=;i<=n+;i++) pre[i]=i;
for(int i=;i<=n;i++) cin>>a[i]; ll ans=lis();
printf("%lld\n",ans);
for(int i=;i<=ans;i++){
printf("%d ",res[i]);
}
printf("\n");
}

带路径模板2

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
using namespace std;
typedef long long ll;
int arr[],liss[],pre[],res[];
int find1(int i,int l,int r){
int mid;
while(l<r){
mid=(l+r)>>;
if(arr[liss[mid]]>arr[i]) r=mid;
else l=mid+;
}
return r;
}
int lis(int len){
int max=;
liss[]=;
for(int i=;i<len;i++){
int index=find1(i,, max-);
if(index==&&arr[liss[index]]>=arr[i]){
liss[index]=i;
continue;
}//增加这条语句主要是pre的影响,不需要路径的话,完全可以去掉。
if(index==max-&&arr[liss[index]]<arr[i]){
liss[max++]=i;
pre[i]=liss[index];
continue;
}
liss[index]=i;
pre[i]=liss[index-];
} int k=liss[max-],t=max-;
while(pre[k]!=k){
res[t--]=arr[k];
k=pre[k];
}
res[t]=arr[k];
return max;
}
int main(){
int n;
cin>>n;
for(int i=;i<n+;i++){
pre[i]=i;
}
for(int i=;i<n;i++){
cin>>arr[i];
}
ll ans=lis(n);
printf("%lld\n",ans);
for(int i=;i<ans;i++){
printf("%d ",res[i]);
}
printf("\n");
}

[dp]最长单调递增子序列LIS的更多相关文章

  1. 动态规划-最长单调递增子序列(dp)

    最长单调递增子序列 解题思想:动态规划 1.解法1(n2) 状态:d[i] = 长度为i+1的递增子序列的长度 状态转移方程:dp[i] = max(dp[j]+1, dp[i]); 分析:最开始把d ...

  2. [C++] 动态规划之矩阵连乘、最长公共子序列、最大子段和、最长单调递增子序列、0-1背包

    一.动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 将待求解问题分解成若干个子问题,先求解子 ...

  3. HD1160FatMouse's Speed(最长单调递增子序列)

    FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. poj1631Bridging signals(最长单调递增子序列 nlgn)

    Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12251   Accepted: 6687 ...

  5. NYOJ17 最长单调递增子序列 线性dp

    题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=17 分析: i=1 dp[i]=1 i!=1 dp[i]=max(dp[j]+1) ...

  6. hdoj 5087 Revenge of LIS II 【第二长单调递增子】

    称号:hdoj 5087 Revenge of LIS II 题意:非常easy,给你一个序列,让你求第二长单调递增子序列. 分析:事实上非常easy.不知道比赛的时候为什么那么多了判掉了. 我们用O ...

  7. nyoj 214——单调递增子序列(二)——————【二分搜索加dp】

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长 ...

  8. nyoj 214 单调递增子序列(二) 【另类dp】

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 ,a2...,an}(0<n<=100000),找出单调递增最长子序列.并求出其长度 ...

  9. nyist oj 214 单调递增子序列(二) (动态规划经典)

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 ,a2...,an}(0<n<=100000).找出单调递增最长子序列,并求出其长度 ...

随机推荐

  1. 工作中你肯定会有关于 Yii2 的小贴士用法,在下面评论分享出来吧。

    场景: 数据库有user表有个avatar_path字段用来保存用户头像路径 需求: 头像url需要通过域名http://b.com/作为基本url 目标: 提高代码复用 此处http://b.com ...

  2. 比较分析与数组相关的sizeof和strlen

    首先,我们要清楚sizeof是C/C++中的一个操作符,其作用就是返回一个对象或者类型所占的内存字节数. 而,strlen是一个函数,函数原型为: size_t strlen(const char * ...

  3. Django之Form详解

    Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 1.创建Form类.View函数处理 from ...

  4. ps 切片 蓝色 灰色 小标志 什么意思

    切片颜色 区分自动切片与用户切片和基于图层的切片.默认情况下,用户切片和基于图层的切片带蓝色标记,而自动切片带灰色标记.-----用户切片就是你需要的切片,其他区域会形成自动切片,可以视为自己不要的, ...

  5. android 电池(三):android电池系统【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/8709838 一.电池系统结构 Android中的电池使用方式主要有三种:AC.USB. ...

  6. HDU2544最短路模板,

    #include<iostream> #include<stdio.h> #include<stdlib.h> #include<algorithm> ...

  7. ThinkPHP 小技巧

    中文截取函数 函数解释: msubstr($str, $start=0, $length, $charset=”utf-8″, $suffix=true) $str:要截取的字符串 $start=0: ...

  8. 编码,charset,乱码,unicode,utf-8与net简单释义

    1.文件分为文本文件和二进制文件﹐不过本质都一样﹐都是些01. 2.计算机存储设备存储的0或1﹐称为计算机的一个二进制位(bit). 3.二进制文件的0和1有专门的应用程序来读﹐所以它们没有什么乱不乱 ...

  9. Hibernate技术

    Hibernate中3个重要的类: 配置类(configuration) 负责管理Hibernate的配置信息,包含数据库连接URL.数据库用户.数据库密麻麻.数据库驱动等. 会话工厂类(Sessio ...

  10. Spark- 计算每个学科最受欢迎的老师

    日志类型 测试数据 http://bigdata.myit.com/zhangsan http://bigdata.myit.com/zhangsan http://bigdata.myit.com/ ...