相信很多小伙伴一般都会在DP里见到他们—>最长XXX子序列 的身影(垃圾玩意儿)原来我也一直不想要去了解这个东西,但是我还是(迫不得已)鼓起勇气去了解了一下这个东西,今天我们的主题就围绕着导弹拦截来展开讲述吧。(其实不管是什么序列,到时候改符号就差不多了)

  首先,这些题题一般就是求一个最长XXX子序列的长度,而导弹拦截呢,就刚好是求长度的一个好问题(我才不是精心挑选的)所以.....

  第一个小问,就是求最长不上升子序列长度,而对于第二个小问题,很多人可能没看明白,其实就是求最长上升子序列的长度,为什么呢?首先,我们假设最少有K个那什么玩意儿才能拦截所有导弹,然后对于第i个系统的任意一个高度,第i+1个系统里肯定有比它高的高度(不然你第i个系统早就把没它高的那玩意儿连上了啊),然后后面的同理,一直这样下去就行了..........

O(N^2)求长度

  这个最暴力的方法,就是我们外层循环枚举一个子序列的结尾,然后内层从1到i-1,枚举这个子序列的倒数第二个,如果接的上,就取最优值,不然.......就啥也不干。

 1 #include <bits/stdc++.h>
 2 int a[100010];
 3 int num[100010];
 4 int dp[100010];
 5 int n=0;
 6 int x;
 7 int ans=0,maxn=0;
 8 using namespace std;
 9 int main()
10 {
11     while(cin>>x)
12         num[++n]=x;
13     for(int i=1;i<=n;i++)//因为开始每一个的序列长度都是自己
14         a[i]=dp[i]=1;
15
16     for(int i=1;i<=n;i++)
17     {
18         for(int j=1;j<i;j++)//枚举结尾和它前面的玩意儿
19         {
20             if(num[i]<=num[j])
21                 a[i]=max(a[i],a[j]+1);//替换
22             if(num[i]>num[j])
23                 dp[i]=max(dp[i],dp[j]+1);
24         }
25     }
26
27     for(int i=1;i<=n;i++)//求最长长度
28     {
29         ans=max(ans,a[i]);
30         maxn=max(maxn,dp[i]);
31     }
32
33     cout<<ans<<endl;
34     cout<<maxn;
35     return 0;
36 }

嗯,交上去就TLE了,看看N,绝对要炸啊,所以,聪明的大佬们果然又........

O(nlogn)求长度

  我们开一个数组dp,然后从a数组(存导弹高度的)1遍历到n

  遇到比dp数组最后一个小的,就接上去

dp[++len]=a[i] 

不然,就只能高铁霸座了,找到第一个小于a[i],的数,直接占位子。但是问题来了,我们怎么找这个数,一般的人都会用而分,但是,像我这种聪明人就选择用STL里面自带的函数啦

lower_bound & upper_bound

假设查找x,

lower_bound是找出一个序列中第一个大于等于x的数

upper_bound是找出一个序列中第一个大于x的数(亲兄弟啊)

然而平常这俩玩意儿都是针对升序的(那还有什么用啊)

但是根据编C++的人的尿性,肯定会有自定义函数的啊,没错,所以.....

lower_bound(dp+1,dp+1+n,x,cmp);

是不是和sort很像,只需要自己打一个比较函数就可以了(但是我懒,所以.....)

lower_bound(dp+1,dp+1+n,x,greater<int>());

和上面差不多,专为懒人设计你值得拥有

但你要知道,它返回的却是个指针(指针什么的最烦了)

所以,你用指针的话.......

int *p = lower_bound(自己想象);

或者直接减去数组开头指针,差就是下标

int p=lower_bound(自己想象)-a;

然后要注意,dp里存的并不是最大不上升子序列,因为它每时每刻(简单快乐)都在更新嗯,就这样,让我们来愉快的模拟样例吧

a={0,389,207,155,300,299,170,158,65}
a[i]=389
dp={0,389}
len=1
dp[len=389]第一个直接进去

a={0,389,207,155,300,299,170,158,65}
a[i]=207
dp={0,389,207}
len=2
dp[len]=207然后,下一个比这一个小,加进去

a={0,389,207,155,300,299,170,158,65}
a[i]=155
dp={0,389,207,155}
len=3
dp[len]=155继续加

a={0,389,207,155,300,299,170,158,65}
a[i]=300
dp={0,389,300,155}
len=3
dp[len]=155哦吼,比这个大了,我们只能踢人了

a={0,389,207,155,300,299,170,158,65}
a[i]=299
dp={0,389,300,299}
len=3
dp[len]=299继续踢人

a={0,389,207,155,300,299,170,158,65}
a[i]=170
dp={0,389,300,299,170}
len=4
dp[len]=170加进去

a={0,389,207,155,300,299,170,158,65}
a[i]=158
dp={0,389,300,299,170,158}
len=5
dp[len]=158加进去

a={0,389,207,155,300,299,170,158,65}
a[i]=65
dp={0,389,300,299,170,158,65}
len=6
dp[len]=65加进去

好啦,模拟完了(好水啊)

最后贡献一下我的代码吧

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int len1=1,len2=1;
 4 int a[100005];
 5 int d1[100005],d2[100005];
 6 int n;
 7 int main()
 8 {
 9     while(cin>>a[++n]);
10     n--;
11     d1[1]=a[1];
12     d2[1]=a[1];
13     for(int i=2;i<=n;i++)
14     {
15         //最长不上升子序列长度
16         if(a[i]<=d1[len1])
17             d1[++len1]=a[i];//加进去
18         else *upper_bound(d1+1,d1+1+len1,a[i],greater<int>())=a[i];//踢人
19         //最长上升子序列的长度
20         if(a[i]>d2[len2])
21             d2[++len2]=a[i];
22         else *lower_bound(d2+1,d2+1+len2,a[i])=a[i];
23     }
24     cout<<len1<<endl<<len2; //输出就好
25     return 0;
26 } 

转载于:https://www.cnblogs.com/hualian/p/11266155.html

最长XXX子序列(什么都好啦)相关推荐

  1. 都能看懂的LIS(最长上升子序列)问题

    LIS问题介绍: 首先来说一下什么是LIS问题: 有一个长为n的数列a0, a1, ......, a(n-1).请求出这个序列中最长的上升子序列的长度.上升子序列指的是对于任意的i<j都满足a ...

  2. 最长公共子序列、最长连续公共子序列、最长递增子序列

    面试中除了排序问题,还会经常出现字符串的子序列问题,这里讲解使用动态规划解决三个常见的子序列问题: 1.最长公共子序列问题(LCS,longest-common-subsequence problem ...

  3. 算法复习——动态规划篇之最长公共子序列问题

    算法复习--动态规划篇之最长公共子序列问题 以下内容主要参考中国大学MOOC<算法设计与分析>,墙裂推荐希望入门算法的童鞋学习! 1. 问题背景 子序列:将给定序列中零个或多个元素(如字符 ...

  4. 算法设计与分析——动态规划(五):最长公共子序列

    分类目录:<算法设计与分析>总目录 相关文章: · 动态规划(一):基础知识 · 动态规划(二):钢条切割 · 动态规划(三):矩阵链乘法 · 动态规划(四):动态规划详解 · 动态规划( ...

  5. 最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr...

    问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y=& ...

  6. leetcode-300 最长上升子序列

    题目描述: 给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度 ...

  7. java实现最长连续子序列_最长公共子序列 ||

    问题:在 前一篇文章 最长公共子序列 | 的基础上要求将所有的最长公共子序列打印出来,因为最长公共子序列可能不只一种. 难点:输出一个最长公共子序列并不难,难点在于输出所有的最长公共子序列,我们需要在 ...

  8. 动态规划——最长上升子序列问题 两种角度及优化算法

    最长上升子序列 OpenJ_Bailian - 2757 一个数的序列 bi,当 b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列( a1, a ...

  9. 触类旁通,经典面试题最长公共子序列应该这么答

    作者 |  labuladong 来源 | labuladong(ID:labuladong) [导读]最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经 ...

最新文章

  1. 6. Oracle闪回特性
  2. SpringBoot在IDEA中实现热部署
  3. <X86汇编语言:实模式到保护模式>四十六 中断和异常的处理与抢占式多任务
  4. 在二分类问题中,准确率一直处于50%上下的解决方法
  5. MySQL存储过程相互调用
  6. 《精通正则表达式》笔记 --- 选择引号内的文字
  7. 功放(耳机/音箱)声压级计算(五)
  8. selenium元素定位——下拉选择框
  9. yoga710怎么进入bios_重装系统看不懂bios?超详细中英文翻译,教你1分钟识别bios各项...
  10. 字幕文件srt格式解析
  11. 用EndNote引用文献出现‘参数错误’解决方式
  12. goodnote笔记同步 Android,goodnotes笔记
  13. 机器人学导论(一)——空间描述和变换
  14. 史上最暖2月谁制造?
  15. Android开发框架汇总
  16. oracle查询语句中select from where group by having order by的解释与应用
  17. JavaSE基础语法中的修饰符
  18. 李开复:大学四年应是这样度过
  19. c语言123l表示什么,C语言的基本数据类型及其表示
  20. 托福百日冲刺—词汇(11)

热门文章

  1. @entity 不限字节长度的类型_面试常考,项目易错,长文详解C/C++中的字节对齐...
  2. C++设计模式(全网最通俗易懂的设计模式进阶)
  3. python 人工智能课程对孩子的好处_少儿编程有什么好处?儿童编程课程学习Python的4大原因...
  4. linux sys伪用户作用,linux用户管理详解
  5. 处理增删改_实现数据的增删改查
  6. 白鹭引擎生成html,初识Egret白鹭引擎 之 创建舞台
  7. php简介的编辑器,推荐几款功能强大的PHP编辑器
  8. apt apt 用法_apt命令–实用用法指南
  9. 具有IDE或IDE插件的Spring Boot Initilizr
  10. 主流Java微服务框架有哪些?-开课吧