最长不下降子序列实现:

利用序列的单调性

  对于任意一个单调序列,如 1 2 3 4 5(是单增的),若这时向序列尾部增添一个数 x,我们只会在意 x 和 5 的大小,若 x>5,增添成功,反之则失败。由于普通代码是从头开始比较,而 x 和 1,2,3,4 的大小比较是没有用处的,这种操作只会造成时间的浪费,所以效率极低。对于单调序列,只需要记录每个序列的最后一个数,每增添一个数 x,直接比较 x 和末尾数的大小。只有最后一个数才是有用的,它表示该序列的最大限度值。

  实现方法就是新开一个数组 d,用它来记录每个序列的末尾元素,以求最长不下降为例,d[k] 表示长度为k的不下降子序列的最小末尾元素。

  我们用 len 表示当前凑出的最长序列长度,也就是当前 d 中的最后那个位置。

  这样就很 easy 了,每读入一个数 x,如果 x 大于等于 d[len],直接让 d[len+1]=x,然后 len++,相当于把 x 接到了最长的序列后面;

  如果 x 小于 d[len],说明 x 不能接到最长的序列后面,那就找 d[1...len−1] 中末尾数小于等于 x 的的序列,然后把 x 接到它后面。举个例子,若当前 x==7,len==8:

1

2

3

4

5

6

7

8

2

3

4

7

7

10

12

29

  d[1]⋯d[5] 均小于等于 x,若在 d[1] 后接 x,则 d[2] 应换成 x,但 d[2]==3,比 x 小,能接更多的数,用 7 去换 3 显然是不划算的,所以 x 不能接 d[1] 后。同理,d[2]⋯d[4] 均不能接x。由于 d[5]≤x 且 x<d[6],7 能比 10 接更多的数,所以选择在 d[5] 后接 x,用 x 替换 10。

  根据这个操作过程,易知数组 d 一定是单调的序列,所以查找的时候可以用二分!二分效率是 logn 的,所以整个算法的效率就是 nlogn 的啦~

输出序列实现:

想了好久,认为 nlogn 做法也是可以输出序列的,这时候需要增加一个 c 数组 用来记录每个元素在最长序列中的位置,即 c[i] 表示 a[i] 被放到了序列的第几个位置。

  输出时,从 数组 a 的尾部开始,逆序依次找出 c 为 len, len-1, len-2 … 3, 2, 1 的元素,并且找到一个就接着寻找 c[i]-1,直到找到 c[i] 为 1 的数。

  举个例子:

a: 13 7 9 16 38 24 37 18 44 19 21 22 63 15
c: 1 1 2 3 4 4 5 4 6 5 6 7 8 3

  len = 8;

  我们从 15 开始倒着找 c 为 8 的元素,找到 63,接着找 c 为 7 的,找到 22,再找 c 为 6 的,找到 21,再找 c 为 5 …… 以此类推。

  从而,我们得出的序列为 63,22,21,19,18,16,9,7

  逆序输出来,就是 7,9,16,18,19,21,22,63

  为什么这个方法是对的呢?倒序查找保证了两个条件:

    - 如果 c 中有多个相同的数,后面的一定是最新更新的;

    - 在保证一条件的前提下,倒序找,后面的数一定可以接到前面数的后面。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#define int long long
#define maxn 1000+10
using namespace std;
inline int read()
{
int x=;
bool f=;
char c=getchar();
for(; !isdigit(c); c=getchar()) if(c=='-') f=;
for(; isdigit(c); c=getchar()) x=(x<<)+(x<<)+c-'';
if(f) return x;
return -x;
}
inline void write(int x)
{
if(x<){putchar('-');x=-x;}
if(x>)write(x/);
putchar(x%+'');
}
int n,len;
int a[maxn],last[maxn],site[maxn];
stack<int> s;
signed main()
{
n=read();
for(int i=;i<=n;i++) a[i]=read();
if(n==)
{
write();
return ;
}
len=;
last[]=a[];
site[]=;
for(int i=;i<=n;i++)
{
if(a[i]>=last[len])
{
last[++len]=a[i];
site[i]=len;
}
else
{
int now=lower_bound(last+,last+len+,a[i])-last;
last[now]=a[i];
site[i]=now;
}
}
printf("max=");
write(len);
printf("\n");
for(int i=n,j=len;i>=;i--)
{
if(site[i]==j)
{
s.push(a[i]);
j--;
}
if(j==) break;
}
while(!s.empty())
{
int put=s.top();
s.pop();
write(put);
printf(" ");
}
return ;
}

请各位大佬斧正(反正我不认识斧正是什么意思)

最长不下降子序列 nlogn && 输出序列的更多相关文章

  1. 最长不下降子序列nlogn算法详解

    今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子 ...

  2. hdu1025 最长不下降子序列nlogn算法

    C - DP Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64bit I ...

  3. 最长不下降子序列nlogn

    b[i]表示长度为i的最长不下降子序列的最小末尾元素的值显然它是单调递增的,满足二分性质,然后就可以愉快地二分啦. #include<iostream> #include<cstdi ...

  4. 最长不下降子序列(线段树优化dp)

    最长不下降子序列 题目大意: 给定一个长度为 N 的整数序列:A\(_{1}\),A\(_{2}\),⋅⋅⋅,A\(_{N}\). 现在你有一次机会,将其中连续的 K 个数修改成任意一个相同值. 请你 ...

  5. tyvj 1049 最长不下降子序列 n^2/nlogn

    P1049 最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 ...

  6. 最长不下降子序列的O(n^2)算法和O(nlogn)算法

    一.简单的O(n^2)的算法 很容易想到用动态规划做.设lis[]用于保存第1~i元素元素中最长不下降序列的长度,则lis[i]=max(lis[j])+1,且num[i]>num[j],i&g ...

  7. 最长不下降子序列//序列dp

    最长不下降子序列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 求最长不下降子序列的长度 输入格式 第一行为n,表示n个数第二行n个数 输出格式 最长不下降 ...

  8. P1020 导弹拦截(nlogn求最长不下降子序列)

    题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...

  9. hdu 1160 FatMouse's Speed(最长不下降子序列+输出路径)

    题意: FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to ...

随机推荐

  1. Delphi百度语音【支持语音识别和语音合成】

    作者QQ:(648437169) 点击下载➨百度语音         语音识别api文档         语音合成api文档 [Delphi 百度语音]支持获取 Access Token.语音识别.语 ...

  2. Maven 的依赖范围

    Maven 在编译项目主代码的时候需要使用一套 classpath,在编译和执行测试的时候会使用另外一套 classpath.最后,实际运行 Maven 项目的时候,又会使用一套 classpath. ...

  3. Abp session和Cookie

    问道 面向Abp 在面向服务的时候,Session 干嘛用? 先把Session 的作用说了,但是在微服务环境下给忽略了,相当于忽略了核心. Session 只是个功能.就是根据Cookie 的Ses ...

  4. winform实现图片的滑动效果

    使用winform实现图片的滑动效果(类似网站首页图片滑动切换效果),结果实现了,但是效果其实不是很理想.也许有更好的方法.         Timer timerSlide = null; //当前 ...

  5. 5_PHP数组_3_数组处理函数及其应用_4_数组和变量间的转换函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 数组和变量间的转换函数 1. list() 语言结构 程序: <?php $info = array('co ...

  6. Jboss部署war以及获取Resource的真实路径

    Jboss部署war以及获取Resource的真实路径 最近在将一个SpringBoot项目打成war包部署到Jboss中,中途遇到一些问题记录. Jboss上部署war 普通的SpringBoot项 ...

  7. foundation-cli创建项目出错的解决方案

    使用foundation-cli创建项目时,如果当前的node版本是12的话就会出现如下错误: fs.js:27 const { Math, Object } = primordials; ^ Ref ...

  8. vue-cli3 一直运行 /sockjs-node/info

    首先 sockjs-node 是一个JavaScript库,提供跨浏览器JavaScript的API,创建了一个低延迟.全双工的浏览器和web服务器之间通信通道. 服务端:sockjs-node(ht ...

  9. sql 树形递归查询

    sql 树形递归查询: with ProductClass(ClassId,ClassName) as ( union all select c.ClassId,c.ClassName from Cl ...

  10. PS1变量设置

    \d :代表日期,格式为weekday month date \H :完整的主机名 \h :主机的第一个名字 \t :显示时间为24小时格式(HH:MM:SS) \T :显示时间为12小时格式 \A ...