LIS——最长不下降子序列

输入一个n,以及n个数据,输出最长的不下降的子序列

大意:

有两种思路:

1.O(n^2)想法

用一个num来记录以该数字为末数字的长度

用一个if限制两个条件,后面小于前面并且后面的长度大于前面的长度+1那么说明需要更新了,最后只要遍历所有的数字在num中看以那个数字为开始点的长度最长。这个比较好理解

#include<cstdio>
const int MAX = 150;
int a[MAX],num[MAX];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 1; i<= n ;i++)
        scanf("%d",&a[i]);
    for(int i = 1; i <= n ; i++){
        num[i] = 1;
        for(int j = 1; j < i ; j++){
            if(a[i] > a[j] &&num[i] < num[j] + 1)
            num[i] = num[j]+1;
        }
    }
     int max = 0;
     for(int i = 1; i <= n ; i++){
            if(max < num[i])
            max = num[i];
     }
     printf("%d",max);
     return 0;
}

2.O(n*logn)想法

这个比较难以理解

用b[k]来记录以该下标为长度,且最后一个数为它的数值

b[1] = a[1],然后循环,判断是否a[i] > b[k],如果是的话,b长度就变长,值就变成a[i],否则的话从长度为1开始找一直找到以长度为k的,因为b是单调递增的,所以在其中找大于b[j],小于b[j+1]这个值的下标,就相当于在一个单调的串中找一个与要找的n相同的值,用二分法,不过以下标为二分的话,l = mid + 1,r = mid -1 ,返回l的值,左闭右开。

#include<cstdio>
using namespace std;
const int MAX = 1010;
int a[MAX],b[MAX];
int main()
{
    int n,k,l,r,mid;
    scanf("%d",&n);
    for(int i = 1; i <= n ; i++)
        scanf("%d", &a[i]);
    b[1] = a[1];
    int i;
    for(i = 2, k = 1;i <= n ; i++){
        if(a[i] > b[k]) b[++k] = a[i];//b[k]存储长度为k的最后一个数字
        else {
             l = 1, r = k;
            while(l<= r){//二分查找
               mid = (l + r)/2;
              if(b[mid] < a[i]) l = mid + 1 ;
              else if(b[mid] > a[i]) r = mid - 1;
              else break;
            }
            b[l] = a[i];
        }
    }
    printf("%d\n",k);
    return 0;
}

也可以调用库函数 lower_bound  二分函数

lower_bound(a, a + n, k) 用二分找a[i]大于k的最小的指针

int dp[maxn];
void solve()
{
    fill(dp, dp + n ,inf);
    for(int i = 0 ; i < n ; i++)
        *low_bound(dp, dp + n ,a[i]) = a[i];
    printf("%d\n",lower_bound(dp,dp+n,inf)-dp);
}

  

时间: 2025-01-01 23:33:42

LIS——最长不下降子序列的相关文章

swust oj 585--倒金字塔(LIS最长不下降子序列)

题目链接:http://acm.swust.edu.cn/problem/585/ Time limit(ms): 3000 Memory limit(kb): 65535 SWUST国的一支科学考察队到达了举世闻名的古埃及金字塔. 关于金字塔的建造一直是一个未解之谜, 有着“西方史学之父”之称的希罗多德认为,金字塔的建造是人力和牲畜,花费20 年时间从西奈半岛挖掘天然的石头运送到埃及堆砌而成.也有不少人认为是外星人修建的.人们发现胡夫金字塔的经线把地球分成东.西两个半球,它们的陆地面积是相等的

SPOJ 3943 - Nested Dolls 最长不下降子序列LIS(二分写法)

现在n(<=20000)个俄罗斯套娃,每个都有宽度wi和高度hi(均小于10000),要求w1<w2并且h1<h2的时候才可以合并,问最少能剩几个. [LIS]乍一看跟[这题]类似,但是仔细看是有区别的,其实就相当于上一题多次求LIS,每次求完LIS后把得到的序列删去,然后重新求LIS,最后输出求LIS的次数,我一开始这样写,果然就TLE了.还是要另辟蹊径. 首先用贪心思想,先按照wi从大到小排序,wi相等的情况下hi从小到大,然后求最长不下降子序列(注意可以等于).输出其长度即可. 想

最长不下降子序列(LIS)

最长上升子序列.最长不下降子序列,解法差不多,就一点等于不等于的差别,我这里说最长不下降子序列的. 有两种解法. 一种是DP,很容易想到,就这样: 1 REP(i,n) 2 { 3 f[i]=1; 4 FOR(j,0,i-1) 5 if(a[j]<=a[i]) f[i]=max(f[i],f[j]+1); 6 } DP是O(n^2)的,我感觉已经不错了不过还有超碉的nlogn的方法. nlogn的方法: 用栈和二分查找. 遇到一个元素a[i],若它不小于栈顶s[top],直接入栈:若大于栈顶,则

动态规划——最长不下降子序列(LIS)

最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] (j<i),使得 A[j]≤A[i] 且 dp[j]+1>dp[i],那么就把 A[i] 跟在以 A[j] 结尾的 LIS 后面,形成一条更长的不下降子序列(令 dp[i]=dp[j]+1). 如果 A[i] 之前的元素都比 A[i] 大,那么 A[i] 就只好自己形成一条 LIS,但是长度为 1

toj 4071 最长不下降子序列nlogn解法

题目描述:给出2D空间中的n只鸟的坐标,射手对其进行射击,要求射击的鸟的坐标越来越大,即对于第i和第i+1只鸟,要求满足:xi<=xi+1 && yi <= yi+1.求最多能射击多少只鸟. 思路:将所有点按照x坐标排序,x坐标相同则按照y坐标排序.则x方向上可以满足限制,对y方向上求最长不下降子序列即可.由于数据量较大,需要采取nlogn的优化算法. 1 #include <algorithm> 2 #include <iostream> 3 #inc

「网络流24题」最长不下降子序列问题

传送门:>Here< 题意: 给定正整数序列$x_1,...,x_n$ (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用$x_1$和$x_n$,则从给定序列中最多可取出多少个长度为$s$的不下降子序列. 思路分析 题意首先就很坑:注意第二问中的取出二字,意味着一个数字最多只能存在于一个LIS中.所以才会有第三问的假设 第一问很简单,直接暴力$O(n^2)$就好了 后面的两问需要借助于网络流.很容易想到

P2766 最长不下降子序列问题

\(\color{#0066ff}{题目描述}\) ?问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. ?编程任务: 设计有效算法完成(1)(2)(3)提出的计算任务. \(\color{#0066ff}{输入格式}\) 第1 行有1个正整数n,表示给定序列的长度.接下来的1 行有n个正整

[网络流24题]最长不下降子序列问题

[luogu 2766] 最长不下降子序列问题 传送门 第一问: \(O(n^2)\) 的DP求LIS 为了下面叙述方便,我们将DP过程讲一遍 子状态:dp[i]表示以a[i]结尾的LIS长度 初始条件:dp[i]=1 状态转移方程:\(dp[i]=dp[j]+1(j<i,a[j]\leq a[i])\) 第二问: 我们发现若a[j]加上a[i]可以构成一个不下降子序列,则\(j<i,a[j] \leq a[i]\) 又发现每个元素只能在一个序列中,考虑拆点 建图方法: 原点S=0,T=2n+

P2766 最长不下降子序列问题 网络流

link:https://www.luogu.org/problemnew/show/P2766 题意 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列. 设计有效算法完成(1)(2)(3)提出的计算任务. 思路 题解来自网络流24题: [问题分析] 第一问是LIS,动态规划求解,第二问和第三问用网络最