最长递增子序列nlogn的做法

费了好大劲写完的  用线段树维护的 nlogn的做法
再看了一下 大神们写的 nlogn  额差的好远
我写的又多又慢  大神们写的又少又快
时间  空间  代码量 哪个都赶不上大佬们的代码

//这是我写的
 #include<iostream>
#include<stdio.h>
#include<map>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 50010;
int a[maxn];
int val[maxn<<2];
vector<int>v;
int getid(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)return val[rt];
int m=(l+r)>>1;int t=0;
if(L<=m)t=max(t,query(L,R,l,m,rt<<1));
if(R>m)t=max(t,query(L,R,m+1,r,rt<<1|1));
return t;
}
void update(int x,int l,int r,int rt,int vv){
if(l==r){
val[rt]=vv;
}else{
int m=(l+r)>>1;
       if(x<=m)update(x,l,m,rt<<1,vv);
   else  update(x,m+1,r,rt<<1|1,vv);
val[rt]=max(val[rt<<1],val[rt<<1|1]);
}
}
int main()
{
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
v.push_back(a[i]);
}
    sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++){
int t=getid(a[i]);
int vv=query(1,t,1,v.size(),1)+1;
ans=max(ans,vv);
update(t,1,v.size(),1,vv);
}
printf("%d\n",ans);
    return 0;
}

//这是大神们的
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
using namespace std;
typedef __int64 ll;
#define maxn 50050
ll a[maxn],dp[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%I64d",&a[i]),dp[i]=1;
int len=0;
for(int i=1;i<=n;i++){
if(i==1){
dp[++len]=a[i];
}
else{
if(a[i]>dp[len]){
dp[++len]=a[i];
}
else{
int pos=lower_bound(dp+1,dp+len+1,a[i])-dp;
dp[pos]=a[i];
}
}
}
printf("%d\n",len);
} 

原文地址:https://www.cnblogs.com/DWVictor/p/10283198.html

时间: 2025-01-13 15:24:51

最长递增子序列nlogn的做法的相关文章

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已经做了实现,但是这种方法时间复杂度太高,查阅相关资料后我发现有人提出的算法可以将时间复杂度降低为O(nlogn),这种算法的核心思想就是替换(二分法替换),以下为我对这中算法的理解: 假设随机生成的一个具有10个元素的数组arrayIn[1-10]如[2, 3, 3, 4, 7, 3, 1, 6,

(转载)最长递增子序列 O(NlogN)算法

原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素.注意d中元素是单调递增的,下面要用到这个性质.首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],

最长递增子序列 O(NlogN)算法

https://www.felix021.com/blog/read.php?entryid=1587&page=3&part=1 感谢作者! 标题:最长递增子序列 O(NlogN)算法 出处:Blog of Felix021 时间:Wed, 13 May 2009 04:15:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1587  内容: 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久

【难】求数组中最长递增子序列,时间复杂度O(nlogn)

题目:<编程之美> P194 写一个时间复杂度尽可能低的程序,求一个数组(length个元素)中最长递增子序列的长度. 注意,本题认为最长递增子序列可以有相等的元素,如 (1,2,2,3,3,4,5,6). 时间复杂度为O(n^2)的程序思路很简单,参考书上的解法一.针对O(n^2)的解法进行改进,利用有序数组的二分查找,可以使得时间复杂度降低.本题的难点在于,建立一个长度为length+1的数组MinV,MinV[i]代表着长度为i的递增子序列最大元素的最小值.而且数组MinV是升序的,理解

51nod 1134 最长递增子序列 (O(nlogn)算法)

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输

HDU 3998 Sequence (最长递增子序列+最大流SAP,拆点法)经典

Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1666    Accepted Submission(s): 614 Problem Description There is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequ

算法面试题 之 最长递增子序列 LIS

找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E6%95%B0%E7%BB%84%E9%83%BD%E6%B2%A1%E7%BB%99%E5%87%BA%E6%9D%A5 我就是理解了一下他的分析 用更通俗易懂的话来说说题目是这样 d[1..9] = 2 1 5 3 6 4 8 9 7 要求找到最长的递增子序列首先用一个数组b[] 依次的将d里面

最长公共子序列 nlogn

先来个板子 #include<bits/stdc++.h> using namespace std; const int N = 1e6+20, M = 1e6+10, mod = 1e9+7, inf = 1e9+1000; typedef long long ll; struct node { int c; int num; } u[N]; int i,j,k = 0,n,m,x,y = 0,T = 0,ans = 0,big = 0,cas = 0,num = 0,len = 0; bo

最大子数组之和、最大子数组之积、最长递增子序列求法

昨天做爱奇艺笔试题,最后一道编程题是求整型数组最长递增子序列,由于时间关系,没有完全写出来,今天重新来做做这一系列题. <1> 最大子数组之和 首先从最简单的最大子数组之和求取.数组里有正数.负数.零.设包含第 i 个元素的子数组的和为 Sum,则Sum的值为 Sum(i) = Sum(i-1) + arrey[i]; 显然如果arrey[i]<=0,则Sum(i)<=Sum(i-1);则必须把Sum(i)=arrey[i];同时maxSum用来保存Sum最大值.时间复杂度为o(n