LIS O(n*lgn)

在第二种算法中,在计算每一个f(i)时,都要找出最大的f(j)(j<i)来,由于f(j)没有顺序,只能顺序查找满足aj<ai最大的f(j),如果能将让f(j)有序,就可以使用二分查找,这样算法的时间复杂度就可能降到O(nlogn)。于是想到用一个数组B来存储“子序列的”最大递增子序列的最末元素,即有

B[f(j)] = aj

在计算f(i)时,在数组B中用二分查找法找到满足j<i且B[f(j)]=aj<ai的最大的j,并将B[f[j]+1]置为ai

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;

const int inf = (1<<31)-1;
const int MAXN = 5e5+10;

int dp[MAXN];
int a[MAXN];
int b[MAXN];

int main()
{
    int n;
    while(~scanf("%d",&n)){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        b[0] = -inf;
        b[1] = a[1];
        int l,m,r,len=1;
        for(int i=2;i<=n;i++){
            l = 0;
            r = len;
            while(l<=r){
                m = (l+r)>>1;
                if(a[i]>b[m])l=m+1;
                else r = m-1;
            }
            b[l] = a[i];
            if(l>len)len++;
        }
        cout<<len<<endl;
    }
    return 0;
}
// 9 2 1 5 3 6 4 8 9 7



LIS O(n*lgn)

时间: 2024-07-29 16:17:44

LIS O(n*lgn)的相关文章

hdu5087 Revenge of LIS II (dp)

只要理解了LIS,这道题稍微搞一下就行了. 求LIS(最长上升子序列)有两种方法: 1.O(n^2)的算法:设dp[i]为以a[i]结尾的最长上升子序列的长度.dp[i]最少也得是1,就初始化为1,则dp[i]=max(dp[i],dp[j]+1)(其中j<i且a[j]<a[i]). int gao() { int ans=0; for(int i=0;i<n;i++) { dp[i]=1; for(int j=0;j<i;j++) { if(a[j]<a[i]) { dp[

小明系列问题――小明序列(LIS)

小明系列问题――小明序列 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4521 Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列.小明想既然找不到,那就自己来发明一个新的序列问题吧!

hdu4521 小明系列问题——小明序列(LIS变种 (线段树+单点更新解法))

链接: huangjing 题目:中文题目 思路: 这个题目如果去掉那个距离大于d的条件,那么必然是一个普通的LIS,但是加上那个条件后就变得复杂了.用dp的解法没有看懂,我用的线段树的解法...就是采用延迟更新的做法,用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新,因为如果在(i-d-1)这个点更新了,会对后面的造成影响,然后线段树的tree[]数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree[]就可以了... 代码: 小明系列问题--小明

RQNOJ 201 奥运大包围:LIS + 拼链成环

题目链接:https://www.rqnoj.cn/problem/201 题意: 开始时n(n<=1000)个人手拉手围成一个圈. 后来这些人中的一些按顺序向里面出圈形成一个新圈.从而使原圈形成一个从高到低,最低与最高连接的圈. 新圈重复相同的操作,直到没有人要出圈为止. 问最少要形成多少个这样的圈. 题解: (1)拼链成环: 对于一个环,可以用两条由环拆开的链拼在一起表示. 例如:有一个环为"1,2,3,4"(1和4连在一起),则可以表示为"1,2,3,4,1,2,

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

[SDOI2014]LIS

题目描述 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案. 如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 输入输出格式 输入格式: 输入包含多组数据. 输入的第一行包含整数T,表示数据组数.接下来4*T行描述每组数据. 每组数据的第一行包含一个整数N,表示A的项数,接下来三行,每行N个整数A1..An,B1.,Bn,C1..Cn,满足1 < =Ai,Bi,Ci < =10^

洛谷U4727小L的二叉树[树 LIS]

题目背景 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣. 所以,小L当时卡在了二叉树. 题目描述 在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随后他又和他人讨论起了二叉搜索树.什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树.设key[p]表示结点p上的数值.对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch]:若其存在右孩子rch,则k

hdu 1087(LIS变形)

Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 31458    Accepted Submission(s): 14128 Problem Description Nowadays, a kind of chess game called “Super Jumping!

poj 2533 Longest Ordered Subsequence(LIS)

Description A numeric sequence of ai is ordered ifa1 <a2 < ... < aN. Let the subsequence of the given numeric sequence (a1,a2, ..., aN) be any sequence (ai1,ai2, ..., aiK), where 1 <=i1 < i2 < ... < iK <=N. For example, sequence (1