蓝桥杯python编程每日刷题 day 20

题目:

给定一个长度为 N 的整数序列:A1, A2, · · · , AN。现在你有一次机会,将其中连续的 K 个数修改成任意一个相同值。请你计算如何修改可以使修改后的数列的最长不下降子序列最长,请输出这个最长的长度。 

最长不下降子序列是指序列中的一个子序列,子序列中的每个数不小于在它之前的数。 

输入格式

输入第一行包含两个整数 N 和 K。

第二行包含 N 个整数 A1, A2, · · · , AN。 

输出格式

输出一行包含一个整数表示答案。
(1)代码:

 
##########################输入部分
n, k = map(int, input().split())
arr = [int(i) for i in input().split()]
 
l = n
notk_max = 0
zd = [0 for i in range(l)]
 
######################################代码部分
 
def bs(t,a,mid):
    if t:
        return mid <= a
    else:
        return mid >= a
 
 
def erf(t,dp,a):#找到新元素在单调栈中的位置,t为False是自左往右第一个小于a,t为True是自左往右第一个大于a
    if not dp:
        return -1
    l,r=0,len(dp)-1
    while l<r:
        mid=(l+r)//2
        if bs(t,a,dp[mid]):#缩头
            l=mid+1
        else:
            r=mid
    return -1 if bs(t,a,dp[l]) else l
 
def zhao2():  # 得出以我结尾的的最长子序列
    global zd, notk_max, arr, k, l
    dp = []
    for i in range(l - k):
        wz = erf(True, dp, arr[i])
        if wz < 0:
            dp.append(arr[i])
            zd[i] += len(dp)
        else:
            dp[wz] = arr[i]
            zd[i] += (wz + 1)
        if zd[i] > notk_max:
            notk_max = zd[i]
 
 
def zhao1():  # 得出以我开头的最长子序列 (不包括自己),以及k在最左侧的not_kmax
    global zd, notk_max, arr, k, l
    dp = []
    for i in range(l - 1, k, -1):
        wz = erf(False, dp, arr[i])
        if wz < 0:
            dp.append(arr[i])
        else:
            dp[wz] = arr[i]
        #######以下为zd赋值
        wz = erf(False, dp, arr[i - k - 1])
        if wz < 0:
            zd[i - k - 1] = len(dp)
        else:
            zd[i - k - 1] = wz
    ########以下得出k覆盖最左 最长不下降子序列长度
    notk_max = len(dp)
    wz = erf(False, dp, arr[k])
    if wz < 0:
        notk_max += 1
 
 
##############################################输出部分
zhao1()
zhao2()
print(notk_max + k)

(1)解析:

1.在代码中的前两个函数为辅助判断二次搜查

def bs(t,a,mid):
    if t:
        return mid <= a
    else:
        return mid >= a
 
 
def erf(t,dp,a):#找到新元素在单调栈中的位置,t为False是自左往右第一个小于a,t为True是自左往右第一个大于a
    if not dp:
        return -1
    l,r=0,len(dp)-1
    while l<r:
        mid=(l+r)//2
        if bs(t,a,dp[mid]):#缩头
            l=mid+1
        else:
            r=mid
    return -1 if bs(t,a,dp[l]) else l

首先我们用t = True,来表示找到在dp这个列表中,比a大的数,首先用二分搜查,来确定比a大的属的序列在哪里,用辅助函数bs来判断,当t为True时,dp[mid]比a小,说明此时mid不是我们要找的序列,将l更新,直到找到我们需要的序列,最后返回l

接下来对主题函数的思想进行分析,首先将k想象为一个可以覆盖元素的滑动窗口,自左往右滑动,k每滑动一次我们就从没有被k覆盖的元素中找最长不下降子序列。而k自左往右滑动完,出现过的最长的最长不下降子序列的长度+k就是我们要的答案

案例 :1,4,2,8,5   。k=2     max=0

(1)k覆盖1,4。从剩余的2,8,5找得最长不下降子序列,2,8。或2,5。max=2

(2)k覆盖4,2。从剩余的1,8,5找得最长不下降子序列 1,8。1,5。max不变

(3)k覆盖2,8。从剩余的1,4,5找得最长不下降子序列1,4,5。max=3

(4)k覆盖8,5。.........max不变

最终max+k就是我们要的答案

2.zhao2的作用是将前(n-k)个数的最佳排序调整到notk——max,并解释一下global用法,用 global 之后的变量将不只局限函数,而是放大于整体程序,在函数中变量的变值可以在函数以外的程序中使用

def zhao2():  # 得出以我结尾的的最长子序列
    global zd, notk_max, arr, k, l
    dp = []
    for i in range(l - k):(此时l为n)
        wz = erf(True, dp, arr[i])
        if wz < 0:
            dp.append(arr[i])
            zd[i] += len(dp)
        else:
            dp[wz] = arr[i]
            zd[i] += (wz + 1)
        if zd[i] > notk_max:
            notk_max = zd[i]

关键操作作用
erf(True, dp, arr[i])找到 arr[i] 在 dp 中的插入位置(第一个 >arr[i] 的数)。
dp.append(arr[i])扩展 LNDS 长度(当前数字比所有 dp 值大)。
dp[wz] = arr[i]替换 dp 中的值,保持最小末尾(优化后续可能性)。
zd[i] 赋值记录以 arr[i] 结尾的 LNDS 长度。

第1步:处理 arr[0] = 3

  1. 查找插入位置
    • erf(True, [], 3) → 空栈直接返回 -1
  2. 更新 dp 和 zd
    • wz = -1 → 执行 dp.append(3) → dp = [3]
    • zd[0] = len(dp) = 1(以 3 结尾的 LNDS 长度为 1)。
  3. 更新全局最大值
    • notk_max = max(0, 1) = 1
iarr[i]dp 变化zdnotk_max
03[3][1,0,0,0,0]1

第2步:处理 arr[1] = 1

  1. 查找插入位置
    • erf(True, [3], 1) → 找第一个 >1 的数(3 在索引 0)。
    • 返回 0
  2. 更新 dp 和 zd
    • wz = 0 → 替换 dp[0] = 1 → dp = [1]
    • zd[1] = wz + 1 = 1(以 1 结尾的 LNDS 长度为 1)。
  3. 全局最大值
    • notk_max 保持 1(未更新)。
iarr[i]dp 变化zdnotk_max
11[1][1,1,0,0,0]1

第3步:处理 arr[2] = 4

  1. 查找插入位置
    • erf(True, [1], 4) → 找第一个 >4 的数(无,返回 -1)。
  2. 更新 dp 和 zd
    • wz = -1 → dp.append(4) → dp = [1, 4]
    • zd[2] = len(dp) = 2(以 4 结尾的 LNDS 为 [1, 4])。
  3. 全局最大值
    • notk_max = max(1, 2) = 2
iarr[i]dp 变化zdnotk_max
24[1, 4][1,1,2,0,0]2

第4步:处理 arr[3] = 2

  1. 查找插入位置
    • erf(True, [1, 4], 2) → 找第一个 >2 的数(4 在索引 1)。
    • 返回 1
  2. 更新 dp 和 zd
    • wz = 1 → 替换 dp[1] = 2 → dp = [1, 2]
    • zd[3] = wz + 1 = 2(以 2 结尾的 LNDS 为 [1, 2])。
  3. 全局最大值
    • notk_max 保持 2
iarr[i]dp 变化zdnotk_max
32[1, 2][1,1,2,2,0]2

3. 最终结果

  • zd = [1, 1, 2, 2, 0]
    • zd[0]=1:子序列 [3]
    • zd[1]=1:子序列 [1]
    • zd[2]=2:子序列 [1, 4]
    • zd[3]=2:子序列 [1, 2]
  • notk_max = 2(前 n-k=4 个元素的最长 LNDS 长度)。

3.接下来为后(n-k)个元素的最佳排序,首先对

从右向左扫描,计算以每个位置开头的 LNDS 长度
 

变量作用
dp动态维护的单调栈(反向递减),存储 ​不同长度反向 LNDS 的最大起始值
zd[i]记录以 arr[i] 开头的 LNDS 长度(用于后续拼接)
notk_max全局最大值,记录反向扫描后的最长 LNDS 长度(用于处理 k 在最左侧的情况)

def zhao1():  # 得出以我开头的最长子序列 (不包括自己),以及k在最左侧的not_kmax
    global zd, notk_max, arr, k, l
    dp = []
    for i in range(l - 1, k, -1):
        wz = erf(False, dp, arr[i])
        if wz < 0:
            dp.append(arr[i])
        else:
            dp[wz] = arr[i]
        #######以下为zd赋值
        wz = erf(False, dp, arr[i - k - 1])
        if wz < 0:
            zd[i - k - 1] = len(dp)
        else:
            zd[i - k - 1] = wz
    ########以下得出k覆盖最左 最长不下降子序列长度
    notk_max = len(dp)
    wz = erf(False, dp, arr[k])
    if wz < 0:
        notk_max += 1

wz = erf(False, dp, arr[i - k - 1])以上的代码用于更新dp之后的代码适用于将前(n-k)个数与后(n-k)连接起来

i - k - 1 的物理意义
  • ​**i**:当前反向遍历的位置(从 n-1 到 k+1)。
  • ​**k**:允许修改的连续元素个数。
  • ​**i - k - 1
    表示前 n - k 个元素中,与当前反向位置 i 对应的“连接点”​**。
    这个位置是 ​前 n - k 个元素的尾部,用于检查是否能与后 n - k 个元素的头部拼接。
 为什么需要 i - k - 1
  • 动态拼接的核心
    修改 k 个元素后,前 n - k 和后 n - k 部分的子序列需要通过某个值连接。
    i - k - 1 标记了前 n - k 部分的最后一个元素,用于判断是否能与后 n - k 部分的第一个元素形成不下降序列。
具体例子说明

输入arr = [3, 1, 4, 2, 8]n=5k=1(修改 1 个元素)。

  • 前 n - k = 4 个元素[3, 1, 4, 2](不修改部分)。
  • 反向遍历范围i = 4, 3, 2(对应 arr[4]=8arr[3]=2arr[2]=4)。
步骤解析:​
  1. ​**i = 4arr[4] = 8)​**:

    • i - k - 1 = 2(即 arr[2] = 4)。
    • 作用:检查 4(前部分的最后一个值)是否能与 8(后部分的第一个值)拼接。
      • 若 4 <= 8,则可以连接,此时 zd[2] 记录反向 LNDS 长度。
      • 本例中 4 <= 8zd[2] 被更新为反向长度 1[8])。
  2. ​**i = 3arr[3] = 2)​**:

    • i - k - 1 = 1(即 arr[1] = 1)。
    • 作用:检查 1 是否能与 2 拼接。
      • 1 <= 2,可以连接,zd[1] 更新为反向长度 2[2, 8])。
  3. ​**i = 2arr[2] = 4)​**:

    • i - k - 1 = 0(即 arr[0] = 3)。
    • 作用:检查 3 是否能与 4 拼接。
      • 3 <= 4,可以连接,zd[0] 更新为反向长度 2[4, 8])。
关键作用总结
场景i - k - 1 的作用
反向遍历时定位前 n - k 个元素的尾部(arr[i - k - 1]),判断是否能与后 n - k 的头部连接。
更新 zd记录前 n - k 个元素中每个位置能向后延伸的 LNDS 长度,用于后续全局拼接。
修改 k 的灵活性通过 zd 和 notk_max 的配合,动态计算修改 k 个元素后的最优解。
 为什么这样设计?
  • 高效性:避免显式枚举所有可能的修改方案,通过反向扫描直接计算可能的最优连接点。
  • 正确性:确保前 n - k 和后 n - k 部分的子序列能通过某个值(可能是修改后的 k 个元素)无缝拼接。
 最终结果的意义
  • ​**zd 数组**:
    • zd[i] 表示以 arr[i] 开头或结尾的 LNDS 长度。
    • 例如 zd = [2, 2, 1, 2, 0] 表示:
      • 从 3 开头的 LNDS 长度为 2([3, 4])。
      • 从 1 开头的 LNDS 长度为 2([1, 2])。
  • ​**notk_max + k**:
    结合正向和反向结果,允许修改 k 个元素时的最长 LNDS(如 [1, 4, 8] 长度为 3)。

总结

i - k - 1 是算法中 ​连接前后子序列的桥梁,通过反向扫描动态更新 zd 数组,确保能高效计算出修改 k 个元素后的最优解。其核心思想是:
​“前 n - k 的末尾必须 ≤ 后 n - k 的开头”​,而 i - k - 1 正是找到这个关键连接点的索引。

4.接下来解释如何取得最大的值

首先我们已经取得了前(n-k)个数和后(n-k)个数的最佳排序,用notk_max代替两个值相加,再用其加上k即可
notk_max = len(dp)
    wz = erf(False, dp, arr[k])
    if wz < 0:
        notk_max += 1

数字示例

输入
  • arr = [3, 1, 4, 2, 8]n=5k=1(修改 1 个元素)。
  • 前 n-k=4 个元素[3, 1, 4, 2]
  • 后 n-k=4 个元素[1, 4, 2, 8](反向扫描从 i=4 到 i=1)。
步骤解析
​**(1) zhao2() 正向扫描后:​**
  • zd = [1, 1, 2, 2, 0](前 n-k 部分的 LNDS 长度):
    • zd[0]=1[3]
    • zd[1]=1[1]
    • zd[2]=2[1,4]
    • zd[3]=2[1,2]
​**(2) zhao1() 反向扫描时:​**
  • 初始化dp = [](反向单调栈),notk_max = 0
  • 处理 i=4arr[4]=8)​
    • dp = [8](反向 LNDS 长度 len(dp)=1)。
    • i-k-1=2arr[2]=4):
      • 检查 4 <= 8(可以拼接)。
      • notk_max = max(0, zd[2] + len(dp)) = max(0, 2+1) = 3
  • 处理 i=3arr[3]=2)​
    • dp = [8, 2](反向 LNDS 长度 len(dp)=2)。
    • i-k-1=1arr[1]=1):
      • 检查 1 <= 2(可以拼接)。
      • notk_max = max(3, zd[1] + len(dp)) = max(3, 1+2) = 3(未更新)。
  • 处理 i=2arr[2]=4)​
    • dp = [8, 4](替换 2 为 4,保持递减)。
    • i-k-1=0arr[0]=3):
      • 检查 3 <= 4(可以拼接)。
      • notk_max = max(3, zd[0] + len(dp)) = max(3, 1+2) = 3(未更新)。
  • 最终 notk_max = 3
    • 对应子序列 [1,4,8](前 [1] + 后 [4,8],修改 arr[0]=1)。
​**(3) 输出 notk_max + k = 3 + 1 = 4**:
  • 实际最长 LNDS 为 [1,1,4,8](修改 arr[0]=1,长度 4)。

关键点总结

操作数学意义示例中的作用
zd[i](正向)前 n-k 部分以 arr[i] 结尾的 LNDS 长度。zd[2]=2 表示 [1,4]
len(dp)(反向)后 n-k 部分以 arr[i] 开头的 LNDS 长度。dp=[8,4] 表示 [4,8]
notk_max 更新取 zd[i-k-1] + len(dp) 的最大值,确保前后部分能拼接。max(3, 2+1)=3[1,4,8])。
+ k修改的 k 个元素作为桥梁,连接前后子序列。长度 3 + 1 = 4[1,1,4,8])。

为什么这样能覆盖所有情况?

  • 不修改 k 的情况
    notk_max 已经记录了前/后部分的最长拼接(如 [1,4,8] 长度 3)。
  • 修改 k 的情况
    通过 + k 直接扩展长度(如修改 arr[0]=1,得到 [1,1,4,8] 长度 4)。
  • 数学保证
    最长 LNDS 必然由以下两种之一构成:
    1. 不修改 k 时的 notk_max
    2. 修改 k 时的 notk_max + k(因为修改的 k 个元素可以完美连接前后部分)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游戏引擎学习第185天

回顾并计划今天的内容 我们完成了开始整理这些数据的工作&#xff0c;但我们还没有机会真正去查看这些数据的具体内容&#xff0c;因为我们只是刚刚开始了数据整理的基本工作。我们收集了大量的信息&#xff0c;但到目前为止&#xff0c;仍然没有足够的可视化工具来帮助我们理…

协议学习——1 NCDSSB

上次面试NCDssb, 今天特意学习下&#xff0c;除了物理层的定义&#xff0c;其实再很多物理层的书上都有&#xff0c;主要是讲下RRC曾怎么玩的。 配置在专用BWP上配置&#xff0c;切实BWP的专用部分

pom.xml与.yml,java配置参数传递

pom.xml与 .yml java配置参数传递 在Java项目中&#xff0c;通过 pom.xml 和 .yml 文件&#xff08;如 application.yml&#xff09;传递变量通常涉及 构建时&#xff08;Maven&#xff09;和 运行时&#xff08;Spring Boot&#xff09;两个阶段的配置。以下是具体的实现方法&…

【解决】:VSCode 中识别不到电脑中的已安装的 Git

# 问题 自己电脑中明明已经安装了 git &#xff0c;但在 vscode 中确识别不到。——————————&#xff08;问题一样就看下去&#xff0c;不一样早早润。省流&#xff01;&#xff01;&#xff01;&#xff01;&#x1f680;&#xff09; # 【第一步】首先要确认你电脑中…

gogs私服搭建

一.介绍&#xff1a; gogs是一个用Go语言开发的自助Git服务&#xff0c;目标是简单、快速搭建Git服务&#xff0c; 支持多种平台&#xff0c;包括Linux、Windows等。它类似于GitHub&#xff0c;但更轻量&#xff0c;适合个人或小团队使用&#xff0c; 在简化git服务搭建流程的…

数位和相等

问题描述 如果一个正整数转化成二进制与转换成八进制后所有数位的数字之和相等&#xff0c;则称为数位和相等的数。 前几个数位和相等的正整数为 11, 88, 99, 6464&#xff0c;…… 请问第 2323 个数位和相等的正整数是多少&#xff1f; import java.util.Scanner; public …

Java-servlet(九)前端会话,会话管理与Cookie和HttpSession全解析

Java-servlet&#xff08;九&#xff09;前端会话&#xff0c;会话管理与Cookie和HttpSession全解析 前言一、什么是会话二、会话管理1. 隐藏的表单域2. 网址重写3. 使用 Cookie3.1 Cookie 的工作流程3.2 Java 中的方法&#xff0c;Cookie 类 三、Cookie 的实现1. 创建 Cookie2…

uniapp开发中store的基本用法和模块化详解

在 UniApp 开发中,状态管理是非常重要的一部分,尤其是在复杂的应用场景下。Vuex 是 Vue.js 的官方状态管理库,可以帮助开发者集中管理应用的状态数据。UniApp 作为基于 Vue.js 的跨平台开发框架,也支持使用 Vuex 进行状态管理。 以下是关于 Vuex 在 UniApp 中的详细用法介…

手写数据库MYDB(一):项目启动效果展示和环境配置问题说明

1.项目概况 这个项目实际上就是一个轮子项目&#xff0c;现在我看到的这个市面上面比较火的就是这个首先RPC&#xff0c;好多的机构都在搞这个&#xff0c;还有这个消息队列之类的&#xff0c;但是这个是基于MYSQL的&#xff0c;我们知道这个MYSQL在八股盛宴里面是重点考察对象…

基于Spring Boot的电动车智能充电服务平台的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【AI学习】人工神经网络

1,人工神经网络(Artificial Neural Networks,ANNs,连接模型,Connection Model) 模仿动物神经网络行为特征(突触联接的结构),进行分布式并行信息处理的算法数学模型。依靠系统的复杂程度,通过调整内部大量节点之间相互连接的关系,从而达到处理信息的目的。 2,前馈神…

场馆预约小程序的设计与实现

摘 要 时代在进步&#xff0c;人们对日常生活质量的要求不再受限于衣食住行。现代人不仅想要一个健康的身体&#xff0c;还想拥有一身宛如黄金比例的身材。但是人们平常除了上下班和上下学的时间&#xff0c;其余空余时间寥寥无几&#xff0c;所以我们需要用体育场馆预约来节省…

笔记:纯真IP库

最近需要使用到ip解析成对应的地域&#xff0c;查找了一些资料&#xff0c;发现纯真ip库&#xff0c;这个比较好用&#xff0c;而且社区版可以获得免费授权。 纯真ip库官网地址&#xff1a;https://www.cz88.net/ python版本git地址&#xff1a;https://github.com/tagphi/cz…

骨密度以及骨密度测量,测量方案,意义;提高;实现方案

骨密度及骨密度测量 骨密度&#xff08;Bone Mineral Density, BMD&#xff09; 是指骨骼单位体积或单位面积内矿物质&#xff08;主要是钙和磷&#xff09;的含量&#xff0c;是评估骨骼强度的重要指标。骨密度降低可能导致骨质疏松&#xff0c;增加骨折风险。 简单分析效果&…

MySQL 体系结构与存储引擎

目录 一、MySQL 体系结构 1. 连接层 (Connection Layer) 2. 服务层 (Server Layer) 3. 存储引擎层 (Storage Engine Layer) 二、MySQL 核心存储引擎比较 1. InnoDB (默认引擎) 2. MyISAM 3. Memory (HEAP) 4. 其他存储引擎 三、InnoDB 存储引擎深度解析 1. 核心架构组…

知识就是力量——物联网应用技术

基础知识篇 一、常用电子元器件1——USB Type C 接口引脚详解特点接口定义作用主从设备关于6P引脚的简介 2——常用通信芯片CH343P概述特点引脚定义 CH340概述特点封装 3——蜂鸣器概述类型驱动电路原文链接 二、常用封装介绍贴片电阻电容封装介绍封装尺寸与功率关系&#xff1…

vue复习1~45

1.关于vue 要理解记忆规则&#xff0c;可以到官网上去找 vue的两种使用方式 vue核心包开发 场景&#xff1a;局部模块改造vue核心包 & vue插件 工程化开发 场景&#xff1a;整站开发 2.创建vue实例 构建用户页面->创建vue实例初始化渲染 学习阶段用开发版本 3.插值…

Netty和Project Reactor如何共同处理大数据流?

在处理大数据流时&#xff0c;Netty和Project Reactor可以协同工作&#xff0c;充分利用Netty的高性能非阻塞IO和Project Reactor的响应式编程模型&#xff0c;实现高效的数据处理和背压控制。以下是如何共同处理大数据流的详细步骤和示例代码&#xff1a; ### 1. Netty和Proj…

【Nginx】location匹配模式与规则

文章目录 一、环境二、匹配模式1. 精准模式2. 前缀模式&#xff08;不继续匹配正则&#xff09;3. 前缀模式&#xff08;继续匹配正则&#xff09;4. 正则模式&#xff08;大小写敏感&#xff09;5. 正则模式&#xff08;大小写不敏感&#xff09; 三、需要注意的地方1. 命中多…

JavaScript基础-定时器

在Web开发中&#xff0c;有时我们需要延迟执行某些操作或者定期重复执行某段代码。JavaScript提供了强大的定时器功能&#xff0c;使得这些需求变得简单易行。本文将详细介绍JavaScript中的定时器&#xff0c;包括setTimeout和setInterval函数的使用方法、注意事项以及一些实际…