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. How MapReduce Works(转)

    原文地址:http://www.cnblogs.com/ggjucheng/archive/2012/04/23/2465820.html 一.从Map到Reduce MapReduce其实是分治算法 ...

  2. Hive报错 Failed with exception java.io.IOException:java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: ${system:user.name%7D

    报错信息如下 Failed with exception java.io.IOException:java.lang.IllegalArgumentException: java.net.URISyn ...

  3. 基于js的网页换肤(不需要刷新整个页面,只需替换css文件)

    1. [代码][JS]代码    <HTML><HEAD><link ID="skin" rel="stylesheet" typ ...

  4. AngularJs 相应回车事件

    最近做项目,要用到AngularJs,之前也有用过一点点,但仅限于数据的绑定,这次项目要整个前端需要使用这个框架,可能是不熟悉的原因,感觉这代码搞起来非常的不便利,:现总结一个响应回车事件: < ...

  5. node.js+express+jade系列三:404错误的配置

    1:新建一个404.jade 2:在app.js后面配置如下代码 app.use(function(req, res){        res.render("404", {sta ...

  6. Runtime Error(ACCESS_VIOLATION)

    1.     while(scanf("%d",&n) )// 错误,会出现  Runtime Error(ACCESS_VIOLATION) while(scanf(&q ...

  7. 并发问题引出ThreadLocal

    ThreadLocal Thread-->人类Runnable-->任务类 多线程并发问题引出ThreadLocal 多线程并发问题的原因: 操作同一个对象,对对象具有读写权限(只读如拍照 ...

  8. BEC listen and translation exercise 37

    You're supposed to do that before 10.30 in the morning, but obviously, if it's an emergency, you can ...

  9. hdu Digital Square(广搜)

    题目:给出n,求出最小的m,满足m^2  % 10^k = n,其中k=0,1,2 http://acm.hdu.edu.cn/showproblem.php?pid=4394 只要有一个x满足条件便 ...

  10. ffmpeg处理RTMP流媒体的命令和发送流媒体的命令(UDP,RTP,RTMP)

    将文件当做直播送至live ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName     re限制输出速率, ...