【LIC】O(nlogn)解法
【LIC--最长递增子序列问题】 在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列。
O(nlogn)算法:所需要的数组
1、数组T
2、增设一个minT[]数组,minT[x]存放长度为x的最长上升子序列的最小末尾数。
3、dp[i],从一到元素T[i]结尾的最长上升子序列的长度;
具体原理转自网络:
设 T[t]表示序列中的第t个数,dp[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设dp[t] = 0(t = 1, 2,
..., len(T))。则有动态规划方程:
dp[t] = max{1, F[j] + 1} (j = 1, 2, ..., t - 1,
且A[j] < A[t])。
现在,我们仔细考虑计算F[t]时的情况。假设有两个元素A[x]和A[y],满足
(1)x < y < t
(2)A[x] < A[y] < A[t]
(3)dp[x] = dp[y]
此时,选择dp[x]和选择dp[y]都可以得到同样的dp[t]值,那么,在最长上升子序列的这个位置中,应该选择T[x]还是应该选择T[y]呢?
很明显,选择T[x]比选择T[y]要好。因为由于条件(2),在T[x+1] ... T[t-1]这一段中,如果存在T[z],T[x] < T[z] < T[y],则与选择T[y]相比,将会得到更长的上升子序列。
再根据条件(3),我们会得到一个启示:根据dp[]的值进行分类。对于dp[]的每一个取值k,我们只需要保留满足dp[t] =
k的所有T[t]中的最小值。设minT[k]记录这个值,即minT[k] = min{A[t]} (F[t] = k)。
注意到minT[]的两个特点:
(1) minT[k]的值是在整个计算过程中是单调不下降的。
(2) minT[]的值是有序的,即minT[1] < minT[2] < minT[3] < ... < minT[n]。
利用D[],我们可以得到另外一种计算最长上升子序列长度的方法。设当前已经求出的最长上升子序列长度为len。先判断T[t]与minT[len]。若T
[t] > minT[len],则将T[t]接在minT[len]后将得到一个更长的上升子序列,len = len + 1, minT[len] = T[t];否则,在minT[1]..minT[len]中,找到最大的j,满足minT[j] < T[t]。令k = j + 1,则有T[t] <= minT[k],将T[t]接在minT[j]后将得到一个更长的上升子序列,更新minT[k] = T[t]。最后,len即为所要求的最长上升子序列的长度。
由于D[]的特点(2),我们在minT[]中查找时,可以使用二分查找(或lower_bound)高效地完成,则整个算法的时间复杂度下降为O(nlogn),有了非常显著的提高。需要注意的是,minT[]在算法结束后记录的并不是一个符合题意的最长上升子序列!
以UVa - 10635 - Prince and Princess为例
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int maxn = *;
- const int INF = 0x7fffffff;
- int main()
- {
- int T;
- scanf("%d", &T);
- for(int kase = ; kase <= T; kase++)
- {
- int n, p, q, x, T[maxn], New[maxn], dp[maxn], minT[maxn], ans = ;
- memset(New, , sizeof(New));
- scanf("%d%d%d", &n, &p, &q);
- for(int i = ; i <= p; i++)
- {
- scanf("%d", &x);
- New[x] = i+;
- }
- int k = ;
- for(int i = ; i <= q; i++)
- {
- scanf("%d", &x);
- if(New[x])
- T[k++] = New[x];
- }
- for(int i = ; i <= k; i++) minT[i] = INF;
- for(int i = ; i < k; i++)
- {
- int m = lower_bound(minT+, minT++k, T[i])-minT; //找到序列中不大于T[i]的最大的数,正因为(二分)查找才使得复杂度变身为n*log(n)
- dp[i] = m; //以元素T[i]结尾的最长上升子序列的长度
- minT[m] = T[i]; //长度为m的上升子序列中最大元素的值;
- ans = max(ans, dp[i]);
- }
- printf("Case %d: %d\n", kase, ans);
- }
- return ;
- }
【LIC】O(nlogn)解法的更多相关文章
- LIS LCS n^2和nlogn解法 以及LCIS
首先介绍一下LIS和LCS的DP解法O(N^2) LCS:两个有序序列a和b,求他们公共子序列的最大长度 我们定义一个数组DP[i][j],表示的是a的前i项和b的前j项的最大公共子序列的长度,那么由 ...
- 关于LIS和LCS问题的o(nlogn)解法
o(n^2)解法就不赘述了,直接解释o(nlogn)解法 LIS最长递增子序列: 先明确一个结论:在长度最大为len的递增序列里若末尾元素越小,该递增序列越容易和后面的子序列构造出一个更长的递增子序列 ...
- 拦截导弹nlogn解法
题目 题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国 ...
- LIS与LCS的nlogn解法
LIS(nlogn) #include<iostream> #include<cstdio> using namespace std; ; int a[maxn]; int n ...
- Codeforces 1029B. Creating the Contest 动态规划O(nlogn)解法 及 单调队列O(n)解法
题目链接:http://codeforces.com/problemset/problem/1029/B 题目大意:从数组a中选出一些数组成数组b,要求 b[i+1]<=b[i]*2 . 一开始 ...
- DP练习 最长上升子序列nlogn解法
openjudge 百练 2757:最长上升子序列 总时间限制: 2000ms 内存限制: 65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候, ...
- 最长公共子序列(稀疏序列)nlogn解法
首先这种做法只能针对稀疏序列, 比如这种情况: abc abacabc. 会输出5 ,,,,就比较尴尬, #include<iostream> #include<cstdio> ...
- 动态规划---最长上升子序列问题(O(nlogn),O(n^2))
LIS(Longest Increasing Subsequence)最长上升子序列 或者 最长不下降子序列.很基础的题目,有两种算法,复杂度分别为O(n*logn)和O(n^2) . ******* ...
- hdu1025 Constructing Roads In JGShining's Kingdom (nlogn的LIS)
题目链接 第一次写nlogn复杂度的LIS,纪念一下. 题目意思是说.有两条平行线.两条平行线都有n个城市,都是从左到右标记为1--n,一条线上是富有城市,一个是贫穷城市.输入n.接下来有n行,p,r ...
随机推荐
- Unity3D之Mecanim动画系统学习笔记(四):Animation State
动画的设置 我们先看看Animation Clip的一些设置: Loop time:动画是否循环播放. 下面出现了3个大致一样的选项: Root Transform Rotation:表示为播放动画的 ...
- ADO.NET 快速入门(二):执行命令
Commands发出针对数据库的数据存储动作.例如,你可以执行一条命令插入或者删除数据.获取更多从数据库移动数据相关的信息,请参考“Update a Database from a DataSet”. ...
- 关于Ajax使用 Callback 函数
1.onreadystatechange 事件 当请求被发送到服务器时,我们需要执行一些基于响应的任务. 每当 readyState 改变时,就会触发 onreadystatechange 事件. r ...
- 美国VPS推荐1GB 50GB可以win
今天向大家推荐一款vps,1GB内存 50G硬盘 8M带宽 不限制流量,并且可以安装windows,年付才290元. 购买链接:http://www.jinbaoidc.com/page.aspx?c ...
- Qt编程18:Qt调色板QPalette的使用
QPalette类有两个枚举类型, 枚举 1.ColorGroup CorGroup指的是3中不同的状态(什么时候设置颜色): 1>Active:获得焦点的状态. 2>Inactive:未 ...
- 发现一个不错的十六进制编辑器-HxD
十六进制编辑器我觉得是个必需的工具,遥想当年用文曲星的时候,Pacmanager.Ewayeditor…… 之前都在用WinHex,好用,但是是个收费软件,老用着破解版心里还是不舒服 后来发现这个名叫 ...
- C++ 不支持模版的分离式编译
1.C++不支持模版的分离式编译,为什么? C++是分别,单独编译,对于每个cpp文件,预编译为编译单元,这个编译单元是自包含文件,编译的时候,不需要其他的文件,编译好了,生成obj文件,然后连接成e ...
- iOS开发笔记系列-基础6(预处理程序)
预处理程序提供了一些工具,使用这些工具更易于开发.阅读.修改程序,也易于将程序移植到不同的系统中.又称为宏. #define #define语句的基本用途之一就是给富豪名称指定程序常量.比如: #de ...
- C# 启动外部程序的几种方法
. 启动外部程序,不等待其退出. . 启动外部程序,等待其退出. . 启动外部程序,无限等待其退出. . 启动外部程序,通过事件监视其退出. // using System.Diagnostics; ...
- sql操作事务SqlTransHelper类实现
具体实现代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...