给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 
求其最长上升子序列长度

Input

第一行一个正整数n,表示序列中整数个数; 
第二行是空格隔开的n个整数组成的序列。

Output

最长上升子序列的长度

 
题解
 
这里给出两种方法,先说经典版本的,设dp【i】表示以以 a【i】为结尾的LST的长度,n方的暴力很好想,显然我们在i之间找到一个最大的LST,且要保证a[j]<a[i],那么显然dp[i]=max(dp[i],dp[j]+1),那么这个dp显然就是在i之前找到一个以小于a[i]结尾元素,用来更新当前的a[i],我们可以直接用满足条件的最长LST来更新就可以了……
所以就用棵线段树来维护一下1到a[i]-1的dp数组的最大值就可以了。代码讲完一起贴。
然后是鬼畜版本的,当然主要是状态,要绕下弯,设dp[i]表示长度为i的LST,结尾元素的最小值,为什么会想到这个,因为显然结尾的值越小,转移更优,然后显然dp数组是单调的,那么就好办了,我们每次枚举一个序列的元素,去更新,更新当前可以更新的最大的长度,更新的条件就是元素x>dp[i],然后二分出最大的i就可以,也只要更新最大的i就可以了为什么就自己想想吧,还比较有思考价值……
 
经典版:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
const int MAXN=;
using namespace std;
struct tree{
int l,r,ma;
}a[*MAXN];
int dp[MAXN],n,ans=,nn=;
int lian[MAXN]; void cl(){
memset(dp,,sizeof(dp));
memset(lian,,sizeof(lian));
} void build(int id,int l,int r){
if(l==r){
a[id].l=l;
a[id].r=r;
a[id].ma=;
return;
}
a[id].l=l;
a[id].r=r;
int mid=(l+r)/;
build(id*,l,mid);
build(id*+,mid+,r);
a[id].ma=max(a[id*].ma,a[id*+].ma);
} int kanxun(int id,int l,int r){
int L=a[id].l,R=a[id].r,mid=(L+R)/;
if(l==L&&r==R){
return a[id].ma;
}
if(r<=mid) return kanxun(id*,l,r);
if(l>mid) return kanxun(id*+,l,r);
else return max(kanxun(id*,l,mid),kanxun(id*+,mid+,r));
} void insert(int id,int aum,int x){
int l=a[id].l,r=a[id].r,mid=(l+r)/;
if(l==r&&l==aum){
a[id].ma=x;
return;
}
if(aum<=mid) insert(id*,aum,x);
else insert(id*+,aum,x);
a[id].ma=max(a[id*].ma,a[id*+].ma);
} int main(){
cl();
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&lian[i]),nn=max(nn,lian[i]);
dp[]=;
build(,,nn);
for(int i=;i<=n;i++){
int j;
if(lian[i]==) j=;
else j=kanxun(,,lian[i]-);
dp[i]=j+;
insert(,lian[i],dp[i]);
}
for(int i=;i<=n;i++) ans=max(ans,dp[i]);
printf("%d",ans);
}

鬼畜版:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<cstring>
using namespace std;
int dp[];
int main(){
memset(dp,,sizeof(dp));
int n,maxi=,l,r,mid,ans=;
scanf("%d",&n);
for(int i=;i<=n;i++){
int x;
scanf("%d",&x);
l=,r=maxi,ans=;
while(l<=r){
mid=(l+r)/;
if(x>=dp[mid]) ans=mid,l=mid+;
else r=mid-;
}
if(ans==maxi) dp[++maxi]=x;
else dp[ans+]=min(dp[ans+],x);
}
printf("%d",maxi);
return ;
}
 

最长上升子序列 LIS nlogn的更多相关文章

  1. AT2827 最长上升子序列LIS(nlogn的DP优化)

      题意翻译 给定一长度为n的数列,请在不改变原数列顺序的前提下,从中随机的取出一定数量的整数,并使这些整数构成单调上升序列. 输出这类单调上升序列的最大长度. 数据范围:1<=n<=10 ...

  2. nlogn 求最长上升子序列 LIS

    最近在做单调队列,发现了最长上升子序列O(nlogn)的求法也有利用单调队列的思想. 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]& ...

  3. 最长递减子序列(nlogn)(个人模版)

    最长递减子序列(nlogn): int find(int n,int key) { ; int right=n; while(left<=right) { ; if(res[mid]>ke ...

  4. 最长上升子序列LIS(51nod1134)

    1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递 ...

  5. 洛谷1439:最长公共子序列(nlogn做法)

    洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...

  6. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  7. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  8. 动态规划(DP),最长递增子序列(LIS)

    题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...

  9. 【部分转载】:【lower_bound、upperbound讲解、二分查找、最长上升子序列(LIS)、最长下降子序列模版】

    二分 lower_bound lower_bound()在一个区间内进行二分查找,返回第一个大于等于目标值的位置(地址) upper_bound upper_bound()与lower_bound() ...

随机推荐

  1. Linux入门基础之一

    Linux 入门基础 一.Linux 系统安装 安装方法网上很多,请自行百度 二.Linux 基本操作 2.1.GNOME图形界面基本操作 操作类似于Windows系统操作 打开每一个文件夹都会打开一 ...

  2. 关于Java网络编程

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...

  3. [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher 题解报告

    来刷kuangbin字符串了,字符串处理在ACM中是很重要的,一般比赛都会都1——2道有关字符串处理的题目,而且不会很难的那种,大多数时候都是用到一些KMP的性质或者找规律. 点击标题可跳转至VJ比赛 ...

  4. Fliptile(枚举+DFS)

    Problem Description Farmer John knows that an intellectually satisfied cow is a happy cow who will g ...

  5. 提供就医帮助的安卓APP

    首先 这是我们团队第一次开发安卓APP,也是我 个人第一个开发项目APP,俗话说:“万事开头难”.所以对于新手的我们来说,做好开发前的准备至关重要.凡事预则立不预则废! 首先我们团队这次开发的提供就医 ...

  6. python 虚拟环境下导入模块出现no matching modules 的解决办法

    问题原因:pip版本过低 解决办法:升级pip                             命令行为   python -m pip install -U pip

  7. Micrometer 快速入门

    Micrometer为最流行的监控系统提供了一个简单的仪表客户端外观,允许仪表化JVM应用,而无需关心是哪个供应商提供的指标.它的作用和SLF4J类似,只不过它关注的不是Logging(日志),而是a ...

  8. smartbits国产版本minismb – windows 10 用户界面无法正常显示

    Minismb测试仪表是复刻smartbits的国产版本,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数和 ...

  9. jvm对象内存分配

    一.jvm简单结构图 1.jvm内存对象分配整体流程: 1.类加载子系统和方法区 类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间.除了类的信息外, ...

  10. Splitting into digits CodeForce#1104A

    题目链接:Splitting into digits 题目原文 Vasya has his favourite number