昨天讲课的时候突然想起来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的更多相关文章

  1. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  2. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  3. 再探jQuery

    再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...

  4. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

  5. Spark Streaming揭秘 Day7 再探Job Scheduler

    Spark Streaming揭秘 Day7 再探Job Scheduler 今天,我们对Job Scheduler再进一步深入一下,对一些更加细节的源码进行分析. Job Scheduler启动 在 ...

  6. 再探ASP.NET 5(转载)

    就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...

  7. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

  8. 第四节:SignalR灵魂所在Hub模型及再探聊天室样例

    一. 整体介绍 本节:开始介绍SignalR另外一种通讯模型Hub(中心模型,或者叫集线器模型),它是一种RPC模式,允许客户端和服务器端各自自定义方法并且相互调用,对开发者来说相当友好. 该节包括的 ...

  9. 深入出不来nodejs源码-内置模块引入再探

    我发现每次细看源码都能发现我之前写的一些东西是错误的,去改掉吧,又很不协调,不改吧,看着又脑阔疼…… 所以,这一节再探,是对之前一些说法的纠正,另外再缝缝补补一些新的内容. 错误在哪呢?在之前的初探中 ...

随机推荐

  1. iOS开发之指定UIView的某几个角(小于4)为圆角

    在iOS开发中,我们经常会遇到View设置圆角的问题,如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore ...

  2. 安装SQLServer2008后Windows防火墙上的端口开放

    1.打开SQL Server 配置管理器-->SQL Server 网络配置-->XXX的协议,启用TCP/IP协议2.打开TCP/IP协议的属性,切至“IP地址”标签,拉至最下端的IPA ...

  3. hdoj 2040

    #include<stdio.h>int i,j,s1,s2;int cha(int a,int b){ s1=0; s2=0;   for(i=1;i<a;i++)   {    ...

  4. CentOS 6.5 IP 设置

    DEVICE=eth0TYPE=EthernetUUID=7d6d54e0-054d-472b-8cc1-080f16ef36c1ONBOOT=yesNM_CONTROLLED=yesBOOTPROT ...

  5. Java学习----对象与对象之间的关系

    1.依赖 对象之间最弱的一种关联方式,是临时性的关联.代码中一般指由局部变量,函数参数,返回值建立的对于其他对象的调用关系. public class A { // 方法一 public void t ...

  6. C# winform 右下角弹窗

    [DllImport("user32")] private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, in ...

  7. nginx——rewrite模块

    1.什么是Nginx的Rewrite规则? Rewrite主要的功能就是实现URL的重写,Nginx的Rewrite规则采用PCRE(Perl Compatible Regular Expressio ...

  8. Android Fragment基础及使用

    同一个app内的界面切换 用Fragment比较合适,因为Activity比较重量级 Fragment 轻量级,切换灵活 --------------------------------------- ...

  9. Insert Interval 面试题leetcode.

    刚开始做这个题的时候绕了好大的圈,对问题的分析不全面,没能考虑所有情况,做的很纠结.后来看了下大神的做法很受启发,改了改代码,最终提交了. public static ArrayList<Int ...

  10. STM32学习笔记——SPI串行通讯(向原子哥学习)

    一.SPI  简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在  EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...