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< ...
随机推荐
- 苹果手机overflow:auto的卡顿
如果你对某个div或模块使用了overflow: scroll属性,在iOS系统的手机上浏览时,则会出现明显的卡顿现象.但是在android系统的手机上则不会出现该问题 通过一个早上的百度搜索和与前端 ...
- CC1310电源
CC1310的电源好扯,把目前遇到的问题记录一下 1 全局LDO和DCDC的输出电压问题 手册上要求的VDDR和VDDR_RF的电压范围是1.7~1.95V,但实际测试时, 在接收状态下无论是全局LD ...
- Integer Break
Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...
- C#获取本机公网IP
/// <summary> /// 获取本机公网IP /// </summary> /// <returns></returns> public sta ...
- UITableView 使用
关键字 •UITableView •UITableViewDataSource •UITableViewDelegate •UITableViewCell •MVC 运行结果
- Appium移动自动化测试之获取appPackage和appActivity
方法一:直接打开Appium,点击左上角机器人图标 选择apk所在位置,如图所示,这里以ContactManager.apk为例 方法二:利用dex2jar和jd-gui这两个工具反编译apk文件 这 ...
- notepad++的CoolFormat代码格式化插件使用
因为notepad++的NppAStyle插件只支持格式化C.C++.C#.Java这四种编程语言的代码,所以本人推荐使用这个CoolFormat的插件,相比于NPPAStyle,CoolFormat ...
- 30分钟groovy快速入门并掌握(ubuntu 14.04+IntelliJ 13)
本文适合于不熟悉 Groovy,但想快速轻松地了解其基础知识的 Java开发人员.了解 Groovy 对 Java 语法的简化变形,学习 Groovy 的核心功能,例如本地集合.内置正则表达式和闭包. ...
- HTTP 协议缓存
http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加 ...
- 初窥Kaggle竞赛
初窥Kaggle竞赛 原文地址: https://www.dataquest.io/mission/74/getting-started-with-kaggle 1: Kaggle竞赛 我们接下来将要 ...