LIS最长上升子序列O(n^2)与O(nlogn)的算法
动态规划
最长上升子序列问题(LIS)。给定n个整数,按从左到右的顺序选出尽量多的整数,组成一个上升子序列(子序列可以理解为:删除0个或多个数,其他数的顺序不变)。例如序列1, 6, 2, 3, 7, 5,可以选出上升子序列1, 2, 3, 5,也可以选出1, 6, 7,但前者更长。选出的上升子序列中相邻元素不能相等。
最容易想到的办法就是用一个数组f[i]保存到达第i个数的LIS
初始化f[i]=1
更新 f[i]=max{f[j]+1,f[i]|a[j]<a[i],1<=j<i}
即在第i位置前的比i小的最大的LIS+1
时间复杂度O(n^2)
#include<cstdio>
#include<iostream>//vj1098
#define ll long long
#define _max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=;
int n,a[N],ans;
int f[N],g[N];
int main()
{
freopen("sample.in","r",stdin);
cin>>n;
for(int i=;i<=n;i++)
scanf("%d",&a[i]),f[i]=g[i]=;
for(int i=;i<=n;i++)
for(int j=;j<i;j++)
if(a[j]<a[i])
f[i]=_max(f[i],f[j]+);
for(int i=n;i>=;i--)
for(int j=n;j>i;j--)
if(a[j]<a[i])
g[i]=_max(g[i],g[j]+);
for(int i=;i<=n;i++)
ans=_max(ans,f[i]+g[i]-);
cout<<n-ans;
return ;
}
从蓝书和网上学到了一种更高效的O(nlogn)的算法
大概思路如下
d[i]表示以i结尾的最长的LIS的长度,则d[i]=max{0,d[j]|j<i,Aj<Ai}+1,最终答案是max{d[i]}。如果LIS中的元素可以相等,把小于号改成小于等于号即可。
假如已经计算出两个状态a,b满足Aa<Ab,且d[a]=d[b],则对于后续所有状态i(即i>a且i>b)来说,a并不会比b差——如果b满足Ab<Aa的条件,a也满足。换句话说,如果我们只保留a,一定不会丢失最优解。
这样,对于相同的d值,最需要保留A最小的一个。我们用g[i]表示d值为i的最小状态编号(如果不存在,g[i]定义为正无穷)。根据上推理可证明
g[1]<=g[2]<=g[3]<=……<=g[n]
#include<cstdio>
#include<iostream>
#define ll long long
#define _max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=;
int n,k,a[N],b[N],o[N],ans,ma,mb;
int j,da[N],db[N],len,la,lb,mid;
int findpos(int *d,int l,int r,int key){
while(l<=r){
mid=(l+r)>>;
if(key>d[mid]){
if(key<=d[mid+])
return mid;
else l=mid+;
}else r=mid-;
}return ;
}
int main(){
cin>>n>>k;
for(int i=;i<=n;i++) scanf("%d",o+i);
for(int i=;i<k;i++) o[i]<o[k]?a[++la]=o[i]:la=la;
for(int i=k+;i<=n;i++) o[i]>o[k]?b[++lb]=o[i]:lb=lb;
da[]=a[],len=,j=;
for(int i=;i<=la;i++)da[a[i]>da[len]?++len:findpos(da,,len,a[i])+]=a[i];
db[]=b[],len=,j=;
for(int i=;i<=lb;i++)db[b[i]>db[len]?++len:findpos(db,,len,b[i])+]=b[i];
for(int i=la;i>=;i--)da[i]?ans+=i,i=:i=i;
for(int i=lb;i>=;i--)db[i]?ans+=i,i=:i=i;
cout<<ans+;
return ;
}
汝佳的code核心
for(int i=;i<=n;i++)g[i]=INF;
for(int i=;i<=n;i++){
int k=lower_bound(g+,g+n+,A[i])-g;
d[i]=k;
g[k]=a[i];
}
LIS最长上升子序列O(n^2)与O(nlogn)的算法的更多相关文章
- 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...
- POJ - 3903 Stock Exchange(LIS最长上升子序列问题)
E - LIS Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Descripti ...
- hdu 5256 序列变换(LIS最长上升子序列)
Problem Description 我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元素都必须是整数. 请输出最少需要修改多 ...
- POJ 3903 Stock Exchange (E - LIS 最长上升子序列)
POJ 3903 Stock Exchange (E - LIS 最长上升子序列) 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action ...
- 动态规划模板1|LIS最长上升子序列
LIS最长上升子序列 dp[i]保存的是当前到下标为止的最长上升子序列的长度. 模板代码: int dp[MAX_N], a[MAX_N], n; int ans = 0; // 保存最大值 for ...
- POJ 1887 Testingthe CATCHER (LIS:最长下降子序列)
POJ 1887Testingthe CATCHER (LIS:最长下降子序列) http://poj.org/problem?id=3903 题意: 给你一个长度为n (n<=200000) ...
- LIS 最长递增子序列
一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...
- 动态规划——E (LIS())最长上升子序列
E - LIS Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- LIS 最长递增子序列问题
一, 最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...
随机推荐
- python项目实践一:即时标记
转自:http://www.code123.cc/1317.html 这是<python基础教程>后面的实践,照着写写,一方面是来熟悉python的代码方式,另一方面是练习使用python ...
- eclipse 3.6 + tomcat 6.0 开发SSH框架学习
1. 下载JDK 1.6.0.35 http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 下载之后 ...
- 【python】迭代器&生成器
源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...
- errorlevel
------siwuxie095 errorlevel 程序返回码 用法:echo %errorlevel% 查看当前程序返回码(即返回值),以知道程序或命令行是否执行成功. DOS在执行完后都有返回 ...
- 修改 TeamViewer ID方法
修改 TeamViewer ID 的方法: 1. 开始 > 运行,录入%appdata%,删除TeamViewer的文件夹:2. 开始 > 运行,录入regedit: 删除 HKEY ...
- 自定义View(三)实现简单的可拖动、可缩放的ImageView
实现技术主要用到1.多点触摸 2.matrix的矩阵,平移.缩放 根据手指的数量判断是进行的拖动.还是缩放动作 package com.bi.xintest; import android.cont ...
- MVC 过滤器 构建会员是否登录
使用环境:在后台管理或者前台有会员中心的情况下使用 使用方式:这是一个用户中心的控制器 我给用户中心主页增加一个特性 [AccountFilter]这是一个过滤器的名字 public class Ac ...
- delphi真随机数发生器
当然不是绝对真随机,是相对真随机数 下载
- jquery easyui tree dialog
<script type="text/javascript" src="<%=request.getContextPath()%>/include/ja ...
- 关于C++的递归(以汉诺塔为例)
关于C++,hanoi塔的递归问题一直是个经典问题,我们学习数据结构的时候也会时常用到, 因为它的时间复杂度和空间复杂度都很高,我们在实际的应用中不推荐使用这种算法,移动n个盘子, 需要2的n次幂减一 ...