再探LIS
昨天讲课的时候突然想起来LIS还有一个东西没搞懂。
又去研究了下。
LIS问题就是要求一个序列中最长不下降或上升子序列,而此问题应用较广,例如很多题会有这样的条件
对于i,j如果他们可以同时选取,则必有|a[i]-a[j]| <= |b[i]-b[j]| (b[i]<b[j])
数学化归一下下得到 b[i]-b[j] <= a[i]-a[j] <= b[j]-b[i]
将i,j各放在一边 有
a[i]-b[i] >= a[j]-b[j]…………①,
a[i]+b[i] <= a[j]+b[j]…………②.
那么我们按其中一个条件排序,即保证排序后的序列对于任意的i,j(i<j)都有①式或②式成立,然后再按另一个条件求LIS即可求出最多可以取多少个。
若要知道取几次可以取完,那么 根据 dilworth 定理, 等同于求其反条件(即原来非降现在就是下降)子序列长度。
那么下面介绍求LIS的几种方法
法一 O(n^2)暴力dp转移
令dp[i]表示以ai结尾的最长不下降子序列长度
则转移方程为dp[i]=max{1,dp[j]+1} a[j]<=a[i]
则max{dp[i]}就是答案
法二 对于上面的dp转移,显然可以用树状数组优化
可以做到(nlogn)
设有 f[i] 表示以大小为i结尾的不下降子序列的最长长度
则dp[i]=max{f[j]}+1,j<=h[i];
max{f[j]}用树状数组维护
具体如下
int g() {
memset(C,,sizeof C);
int ans=;
for(int i=;i<=n;i++) {
dp[i]=;
int t=query(h[i])+;
ans=max(ans,t);
add(h[i],t);
}
return ans;
}
注意:1.可以不保留dp数组,直接更新ans即可。
2.如果max{h[i]}过大,则需要离散化
法三 二分法求LIS O(nlogn)
设s[i]表示以长度为i的上升子序列的最后一位的最小值。
则每次可以用a[i]去更新s[i]数组
显然s数组是不下降的
int h[Maxn],s[Maxn],ans,n;
int f(){
s[ans=]=-INF;
for(int i=;i<=n;i++){
int v=h[i];
if(v>s[ans])s[++ans]=v;
else*lower_bound(s+,s+ans+,v)=v;
}return ans;
}
对于第6行得到新的答案,根据s数组的定义,显然正确。
然后如果v<=s[ans],则此时不能更新ans,但是可以更新s数组,如何更新呢?跟上面一样,我们要找到一个s[i] (< v) 则此时可以用这个s[i]来更新s[i+1],而实际上只有这一个更新是有意义的,因为对于<=i的更新只会使答案更劣,对于i+2及以上的不能保证序列合法。
更新之后就会更新s[i+1]的值,又s[i]是最大的满足s[i]<v的i,所以s[i+1]必是最小的>=v的值,用lower_bound就好了。
同理如果要求非降子序列 改成下面这样即可
int h[Maxn],s[Maxn],ans,n=;
int f(){
s[ans=]=-INF;
for(int i=;i<=n;i++){
int v=h[i];
if(v>=s[ans])s[++ans]=v;
else*upper_bound(s+,s+ans+,v)=v;
}return ans;
}
可以发现改了两处,一是第6行的>= 二是lower_bound变成了upper_bound
请自行思考为什么这样可行
再探LIS的更多相关文章
- 【再探backbone 02】集合-Collection
前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...
- ViewPager+Fragment再探:和TAB滑动条一起三者结合
Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...
- 再探jQuery
再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...
- [老老实实学WCF] 第五篇 再探通信--ClientBase
老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...
- Spark Streaming揭秘 Day7 再探Job Scheduler
Spark Streaming揭秘 Day7 再探Job Scheduler 今天,我们对Job Scheduler再进一步深入一下,对一些更加细节的源码进行分析. Job Scheduler启动 在 ...
- 再探ASP.NET 5(转载)
就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...
- 再探java基础——break和continue的用法
再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...
- 第四节:SignalR灵魂所在Hub模型及再探聊天室样例
一. 整体介绍 本节:开始介绍SignalR另外一种通讯模型Hub(中心模型,或者叫集线器模型),它是一种RPC模式,允许客户端和服务器端各自自定义方法并且相互调用,对开发者来说相当友好. 该节包括的 ...
- 深入出不来nodejs源码-内置模块引入再探
我发现每次细看源码都能发现我之前写的一些东西是错误的,去改掉吧,又很不协调,不改吧,看着又脑阔疼…… 所以,这一节再探,是对之前一些说法的纠正,另外再缝缝补补一些新的内容. 错误在哪呢?在之前的初探中 ...
随机推荐
- vs里 .sln和.suo 文件
Net解决方案下 .sln文件和.suo文件的解释:When a Web site is created, a solution file (.sln) and a hidden solution u ...
- 总结Widows 7 Start->Run 命令
Widows + R基本上成为很常用的方式,那么通过Windows + R我们可以在运行中做什么手脚呢. 下面从最基本的系统命令说起 notepad--------打开记事本 services. ...
- java获取数据库数据表的元数据
Connction conn; DatabaseMetaData dmd=conn.getMetaData();//获取数据库元数据 PreparedStatment ps; ps.getParame ...
- 关于使用iframe标签自适应高度的使用
在ifrome内设定最小高度,(此方法只适用于页面内切换高度不一.但是会保留最大高度,返回后保持最大高度不再回到最初页面的高度) <iframe id="one4" widt ...
- CSS负边距自适应布局三例
单列定宽单列自适应布局: <!DOCTYPE HTML> <html> <head> <meta charset=”UTF-8″> <title& ...
- call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.
call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 注意:该函数的语法与 apply() 方法的语法几乎完全相同,唯一的区别在于,apply()方法接受的是一个参 ...
- 基于php-fpm的配置详解[转载]
php自带php-fpm/usr/local/php/etc/php-fpm.confpid = run/php-fpm.pidpid设置,默认在安装目录中的var/run/php-fpm.pid,建 ...
- python模块之hashlib加密
40.加密模块:hashlib 1. >>> import hashlib >>> ret1 = hashlib.md5() ...
- Android RecyclerView Adapter 新式用法之SortedListAdapterCallback
引言 前几天在同事的提醒下发现V7中有了一个新的工具类SortedListAdapterCallback,配合RecyclerView Adapter和SortedList一起使用更加方便的管理我们在 ...
- java高精度数组
POJ1205 递推公式为a[i] = 3*a[i-1] - a[i-2], a[1] = 1,a[2] = 3 , i 最高为100; 搞懂了使用BigInteger开数组. import java ...