【模板】O(nlongn)求LIS
合理运用单调性降低复杂度
平常用的都是O(n^2)的dp求LIS(最长不下降子序列)
这里介绍O(nlogn)的算法
分析
- 对于可能出现的
x<y<i
且A[y]<A[x]<A[i]
,则x相对于y更有潜力- 因为接下来可能出现
A[y]<A[z]<A[x]
而x<z<i
;
- 因为接下来可能出现
- 我们以
f[i]
表示前i
个数中的LIS最长长度;- 当出现
f[x]==f[y]
时,就应该选择x
而不会是y
- 当出现
- 我们可以得到以下思想
- 首先根据
f[]
值分类,记录满足f[t]=k
的最小的值a[t]
,记d[k]=min{a[t]},f[t]=k
. - 1.发现
d[k]
在计算过程中单调不上升 - 2.
d[1]<d[2]<...<d[k]
(反证) 1 2 3 8 4 7
- 首先根据
- 由此得到解法
- 设当前最长递增子序列为len,考虑元素a[i];
- 若
d[len]<a[i]
,则len++
,并将d[len]=a[i]
;否则,在d[0-len]
中二分查找,找到第一个比它小的元素d[k]
,并令d[k+1]=a[i]
代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 41000;
int a[N]; //a[i] 原始数据
int d[N]; //d[i] 长度为i的递增子序列的最小值
int BinSearch(int key, int* d, int low, int high) {
while(low<=high) {
int mid = (low+high)>>1;
if(key>d[mid] && key<=d[mid+1])
return mid;
else if(key>d[mid]) low=mid+1;
else high=mid-1;
}
return 0;
}
int LIS(int* a, int n, int* d) {
int i,j;
d[1]=a[1];
int len=1; //递增子序列长度
for(i=2; i<=n; i++) {
if(d[len]<a[i]) j=++len;
else j=BinSearch(a[i],d,1,len)+1;
d[j]=a[i];
}
return len;
}
int main() {
int t;
int p;
scanf("%d",&t);
while(t--)
{
scanf("%d",&p);
for(int i = 1; i <= p; i++) scanf("%d",&a[i]);
printf("%d\n",LIS(a,p,d));
}
return 0;
}
【模板】O(nlongn)求LIS的更多相关文章
- nlogn求LIS(树状数组)
之前一直是用二分 但是因为比较难理解,写的时候也容易忘记怎么写. 今天比赛讲评的时候讲了一种用树状数组求LIS的方法 (1)好理解,自然也好写(但代码量比二分的大) (2)扩展性强.这个解法顺带求出以 ...
- Codeforces 486E LIS of Sequence --树状数组求LIS
题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i] ...
- hdu5256 二分求LIS+思维
解题的思路很巧,为了让每个数之间都留出对应的上升空间,使a[i]=a[i]-i,然后再求LIS 另外二分求LIS是比较快的 #include<bits/stdc++.h> #define ...
- hdu 1025LIS思路同1257 二分求LIS
题目: Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- HDU 5773 The All-purpose Zero(O(nlgn)求LIS)
http://acm.hdu.edu.cn/showproblem.php?pid=5773 题意: 求LIS,其中的0可以看做任何数. 思路: 因为0可以看做任何数,所以我们可以先不管0,先求一遍L ...
- poj1631——树状数组求LIS
题目:http://poj.org/problem?id=1631 求LIS即可,我使用了树状数组. 代码如下: #include<iostream> #include<cstdio ...
- HDU1087(树状数组求LIS)
题是水题,学习一下用树状数组求LIS. 先离散化一下,注意去重:然后就把a[i]作为下标,dp[i]作为值,max作为维护的运算插进树状数组即可. 如果是上升子序列,询问(a[i] - 1):如果是不 ...
- UVA 10635 Prince and Princess—— 求LCS(最长公共子序列)转换成 求LIS(最长递增子序列)
题目大意:有n*n个方格,王子有一条走法,依次经过m个格子,公主有一种走法,依次经过n个格子(不会重复走),问他们删去一些步数后,重叠步数的最大值. 显然是一个LCS,我一看到就高高兴兴的打了个板子上 ...
- 树状数组求LIS模板
如果数组元素较大,需要离散化. #include <iostream> #include <cstdio> #include <cstring> #include ...
随机推荐
- Mac安装python 环境& pychaem
一.文档说明 在Mac上其实自带python环境,但是很多的library安装python是2.7的版本. 验证:可以在终端Terminal中输入:python 如下图是未安装之前,但是咱们需要在自己 ...
- Solon 的过滤器 Filter 和两种拦截器 Handler、 Interceptor
在web开发中,过滤器.拦截器是经常用到的功能.它可以帮我们限制流量.验证是否登陆.记录日志以及统计执行效率等等. 今天主要交流一下 Solon 框架中的过滤器和拦截器. Solon 是什么框架? S ...
- Ubuntu执行命令时,不sudo提示权限不足,sudo提示找不到该命令
问题:Ubuntu执行命令时,不sudo提示权限不足,sudo提示找不到该命令 补充描述:尝试将命令所在路径添加到/etc/profile中(所有用户环境变量),结果sudo -i切换到root用户后 ...
- Introduction to x265 Rate Control Algorithm
The rate control in x265 is the same as x264's implementation, which is mostly empirical. It include ...
- OO第一单元总结——表达式求导
第一次作业 (1) UML结构图 (2)结构分析 Polynomial 类是对输入的字符串进行预处理,其中包括判断格式是否合法,运算符简化,分割成项等方法. Polynomial处理后得到的每一个项的 ...
- SpringBoot系列——事件发布与监听
前言 日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱.短信提示用户,通常我们都是这样写: /** * 用户注册 */ @GetMapping("/userRegi ...
- 在ZOHO企业网盘中如何快速搜索文件?
现在越来越多的企业采用企业网盘来存储文档和资料,而且现在市面上的企业网盘各种各样.在使用企业网盘过程中,很多用户会问到企业网盘中如何快速搜索文件的问题.但是无论是"标签"功能还是普 ...
- docker运行mysql数据库
1.搜索镜像源是否有mysql镜像 执行语句: sudo docker search mysql 2.拉取需要版本的mysql,执行语句: docker pull mysql:5.7 3.查看安装 ...
- [设计模式] 设计模式课程(二十)--命令模式(Command)
概述 "行为变化"模式:组件构建过程中,组件行为的变化经常会导致组件本身剧烈的变化."行为变化"模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现 ...
- 戴尔 R730xd 服务器更改管理口密码 图文教程
一.开机根据提示按F2进入配置界面 - 选择中间的iDRAC Setting选项,回车确认 二.进入之后选择 user configuration 选项 三.在change password 处键入新 ...