5.5【A】

P1020

就是说递减;

一个是要求最长的递减序列长度

对于每个来的导弹,是要选择,到底给已有的系统,还是新起一个系统

如果是贪心的话,就是先看先有的系统能不能拦截,如果能拦截就选差值最小的放进去;如果不能就新起一个系统;

这样不一定是数量最少的,但应该是能找到拦截数量最多的

不对,也不一定,比如原来是一个比较大的数,但是来了个低的,直接就导致后面可能接上的,都接不上了,

那先按照暴力法,就是遍历每个导弹的选择

即导弹来了后,都先后执行给已有系统和新起一个系统,那复杂度将是2^n级别

如果选给已有系统,那就给最接近的系统,然后更新数据

如果新起系统,就向维护系统的数据结构当中插入一个新节点

然后为了加快搜索,维护结构选择搜索树

但是情况数是2^n级别的,每个选择后,对应的树也都不同,复杂度也是非常庞大,一个树是n级别的,那空间复杂度是n*2^n

假设不在乎成本,最后要找的就是2*n中对应的节点最少的树以及2^n中所有的树所有节点里更新次数最多的那一个节点(这个可以在节点结构中保存一个cnt,并在维护中不断更新max,来省掉最后的遍历查找max)

但这个暴力法复杂度完全无法接受,如何优化?

我还没有求解最长非递增子序列的经验,先引导我如何解决这个问题?

说白了就是两个子问题,一个是给定数列的最长非递增自序列,一个是序列中非递增子序列的最少数量

求解最长非递增子序列

那每个导弹的选择,换个语言就是,对于序列中第I个数,以第I个数为结尾时的最长长度,

如果选择以它为结尾,那就是在先有保持的子序列长度再加个1,即cur+1

如果不以它为结尾,那此时的最长长度是dp[i-1]

但如何知道cur?

dp[i]=max(dp[i-1],cur+1)

这个想法不对,因为i所在的序列,它的上一个元素并不一定是i-1,从最优角度就是max(),就是每个dp[i]的确定,都要找一下前面的maxdp,

也不一定就是maxdp,而是满足hi条件的maxdp

这样每个dpi在确定时,都能保证hi<hi-1

dp[i] = 以第 i 个导弹(高度 h[i]结尾的最长不升子序列长度,说i就是以i为结尾的最长序列

那结果就是max(dp[i])

那这个说是dp,但其实没想象的那么复杂,还是靠维护多个数据结构维护出来,dp是长度信息,h[i]是高度信息

所以要确定dp[i],N的长度,关键就在于如何查找满足hi条件的maxdp

如果顺序查找,就是n^2复杂度

如果二分查找,就是n*log(n)

这个二分查找,是在查找所有所有满足条件hi条件里的dp的最大值

但并非一次独立的二分查找

假设找到了满足hi条件的序列x,那接下来应该在找x里找对应dp的最大值

但h数组没有单调性,所以也不能二分查找;

用一个数据结构,来维护各个长度下,最好的数值;就是一个数组

那这个数组天然的就是单调递减结构,因为要想让序列长度增加,就必须削减数值;

新元素来的时候,从右向左遍历,找到第一个大于该数值的位置,这样表示元素能插入进去,假设其长度为x,那么插入该元素后,长度变为x+1,那么就需要尝试更新x+1的数值

变为顺序就是,第一个小于该数值的位置上,这样

tail[i]=max(tail[i],h[i])

但是如何利用这个数组知道dp[i]max?

应该是可以的,因为每个元素来了后,去找第一个小于的元素,实际上就是在查找满足hi条件的位置,同时下标的含义还是数组长度,所以也代表了满足条件的最长序列长度,即dpmax

所以最后的最长序列,就是tail的长度

初始化:

先是让tail[0]=h[0]

然后来了新元素后,(由于元素是一个一个来,所以即使更新前面的,也不会对后面的值产生影响)

遍历到tail的尾部

如果当前元素小于h[i]

那么tail[i]=max(tail[i],h[i]),但是都说是小于了,应该也不用取max,就直接是覆盖,tail[i]=h[i]

如果查到最后都没找到,那就新插入一个元素,值为h[i]

求最少的递增序列长度

仿照之前的思想,来了一个元素后,肯定希望往最最接近的序列中插入

以tail[i[,数组下标表示第几个系统,数值代表此时保存的长度

但是这样的贪心思路不一定能找到最优解

就是说去找序列当中,递增序列的最长长度,假设对应的序列为X,那么X当中的每个元素,都会迫使当前系统新增一个设备;因为之前的系统,无论如何也接收不了;

所以只需要去找最长的

如果暴力DP。DPi表示以i为结尾的最长长度,那么hi必须满足大于hj

dp[i]=1+max(dp[j])

如果tail数组优化,tail[i]就是长度为i时,对应的最小数值,这样才能接更多的,那数组天然是递增的;那要找的就是第一个大于的,这样才是由前面的最大小于的元素来的

for

如果大于

求解过程当中,要考虑到等于的情况,

如果等于能接上的话,就是非递增,就是

如果等于不能接上,那就是严格递增,那找条件的时候,就应该是第一个小于等于的

上面就是没考虑等于的情况

就是找在满足条件时的下标用的是顺序遍历,需要用二分法降一降复杂度

二分编写

对于二分的编写,考虑如果数组里元素都不满足时的情况,左侧l和右侧r的值会如何变化,最终值是怎样的

如果写l<r,假设在单调减里找,如果都大于,那么l一直加,

如果要找的元素在最右侧,r的位置始终没动,如果l到r的前一个位置,那么m无法到r的位置,只会是到l,依然不满足条件,那么l+1到r的位置,但是此时就退出循环了;也无法验证最后一个位置了;此时m无法验证n-1位置,最高到n-2

如果都小于,那么r到l前一个位置时,m可以验证l位置,此时返回m是合理的,因为m可以到l,可以验证0的位置;

对于m,其始终,一定会是数组中的某个元素

我上面说的这个是在左闭右闭条件下的情况,m无法验证n-1

但如果是左闭右开,即r=n,而不是n-1的情况

那么l就可以到达最右侧,即n-1的位置,那么m就可以验证n-1

所以此时就消除了除法无法验证最右端的问题

所以一定要用左闭右开

P11680

先是给定LR,先求[1,L]和[1,R]的数量

对于N位长的,

如果为奇数,设N=2k+1,那么自然也包含I<k的所有的首中尾相等数;那么只需要求N所对应的首中尾相等数即可;然后i<k的情况都可以通过组合计数求得

如果为偶数,设N=2k,那么就是求2k-1时,I<k的首中尾相等数,直接组合计数算,不必再求最高位的

对于组合计数计算,如果是2i+1位的数,那么3位,即首中尾是固定相等,占用的,有9种可能;2i+1-3=2i-2尾是自选的,相等于一个2i-2的位数的数,有几种可能,即10^(2i-2)

所以是9*10^(2i-2)

然后就是限制上限的奇数N位上的相等数构造,其首中尾数的下标分别是0,i,2i,设对应上的数字分别是abc

那么就是求abc中,a=b=c所满足的数的数量

对于最高位a,首先对于a-1的数,是随便构造的,即a-1个;

然后对于等于最高位a的情况,就是min(a,b,c)个,所以是a-1+min(a,b,c)个

也不用dfs来遍历构造

dfs(当前位数i,是否紧贴tight,当前相等数字)

1.转为字符串,得到长度N

2.判断N的奇偶

如果是偶数,就是9*10^(2i-2),求和

如果是奇数,就是9*10^(2i-2),求和再加上a-1+min(a,b,c)个

再维护一个数组,表示对于i=0,1,2,3时,不限制上限的取值数量

相关推荐
云qq3 小时前
C++ 原子操作
开发语言·c++·算法
xrgs_shz3 小时前
基于轻量化浅层卷积神经网络的手写数字识别
算法·matlab·cnn
计算机安禾3 小时前
【计算机网络】第10篇:距离矢量路由算法——Bellman-Ford方程与RIP协议的特性分析
计算机网络·算法
机器学习之心3 小时前
基于开普勒优化算法(KOA)优化CNN-BiGRU-Attention混合网络的时间序列预测模型,MATLAB代码
算法·时间序列预测模型·开普勒优化算法
Java成神之路-4 小时前
【LeetCode 刷题笔记】367.有效的完全平方数 | 二分查找经典刷题题解
算法·leetcode
一切皆是因缘际会11 小时前
从概率拟合到内生心智:2026 下一代 AI 架构演进与落地实践
人工智能·深度学习·算法·架构
Java成神之路-11 小时前
【LeetCode 刷题笔记】34. 在排序数组中查找元素的第一个和最后一个位置 | 二分查找经典刷题题解
算法·leetcode
不忘不弃11 小时前
用BFS方法求解平分汽油问题
算法·宽度优先
AI科技星12 小时前
全域数学·72分册·射影原本 无穷维射影几何卷细化子目录【乖乖数学】
人工智能·线性代数·算法·机器学习·数学建模·数据挖掘·量子计算