1 条题解
-
0
一、题目回顾
题目核心
给定长度为
L的线性位置序列,其中N个位置是香蕉(坐标严格递增),其余为苹果。可使用至多M次魔法将香蕉转为苹果,求转换后最长的连续苹果段长度。输入输出要求
- 输入:第一行
N(香蕉数)、M(魔法次数)、L(总长度);第二行N个严格递增的整数,表示香蕉的位置。 - 输出:最长连续苹果段的长度。
二、用户代码的核心思路分析
用户代码采用滑动窗口(双指针) 解决问题,核心逻辑围绕“维护一个最多包含
M个香蕉的区间,该区间内的香蕉可全部转为苹果,区间整体即为连续苹果段”展开,具体思路如下:1. 状态标记
用数组
a标记每个位置的类型:a[i] = 1:位置i是香蕉;a[i] = 0:位置i是苹果。
2. 滑动窗口定义
- 左指针
l、右指针r:表示当前窗口的左右边界,窗口[l, r]内的香蕉数量为sum。 - 核心约束:窗口内香蕉数量
sum ≤ M(可通过魔法转为苹果,窗口整体为连续苹果段)。
3. 窗口移动规则
- 扩张右边界:若当前窗口内香蕉数
sum ≤ M,说明窗口合法,先更新最长苹果段长度ans,再向右移动r扩大窗口;若新加入的r位置是香蕉,sum加1。 - 收缩左边界:若当前窗口内香蕉数
sum > M,说明窗口非法,需向右移动l收缩窗口;若移出的l位置是香蕉,sum减1。
4. 终止条件
当左指针
l超过总长度L,或右指针r超过总长度L时,窗口无法再扩展/收缩,循环终止。三、用户代码(带详细逐行注释)
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; // 该常量未实际使用,仅占位 // 如果某个区间的香蕉数量小于等于m 那就是合理的 可以选的 int n,m,a[10000010],L,t,ans; // 变量说明: // n:香蕉的数量;m:魔法道具使用次数; // a[]:标记位置是否为香蕉(a[i]=1是香蕉,0是苹果); // L:苹果和香蕉的总数量(总长度); // t:临时变量,用于读取香蕉位置; // ans:最终答案,最长连续苹果段长度 // n是有n个香蕉 L是总距离 // a[i]=0 认为坐标i上是 苹果 // a[i]=1 认为坐标i上是 香蕉 int main(){ // 输入:香蕉数n、魔法次数m、总长度L cin>>n>>m>>L; // 遍历n个香蕉,标记对应位置为香蕉(a[t]=1) for(int i=1;i<=n;i++){ cin>>t; // 读取第i个香蕉的位置t a[t]=1; // 标记位置t为香蕉 } // 滑动窗口初始化:左指针l=1,右指针r=0(初始窗口为空),sum=0(窗口内香蕉数) int l=1,r=0,sum=0; // 滑动窗口主循环:左指针不超过总长度,且右指针不超过总长度时循环 while(l<=L&&r<=L){ // 情况1:当前窗口内香蕉数≤m(窗口合法,可扩展) if(sum<=m){ ans=max(ans,r-l+1); // 更新最长苹果段长度(当前窗口长度为r-l+1) r++; // 右指针右移,扩大窗口 if(a[r]==1) sum++; // 若新加入的位置是香蕉,窗口内香蕉数+1 }else{ // 情况2:当前窗口内香蕉数>m(窗口非法,需收缩) if(a[l]==1) sum--; // 若左指针位置是香蕉,移出后窗口内香蕉数-1 l++; // 左指针右移,收缩窗口 } } // 输出最长连续苹果段长度 cout<<ans; return 0; }四、样例走查(验证代码正确性)
以样例输入为例,逐步模拟代码执行过程:
样例输入
5 2 100 10 30 55 56 90初始化
n=5, m=2, L=100;a[10]=a[30]=a[55]=a[56]=a[90]=1,其余a[i]=0;l=1, r=0, sum=0, ans=0。
关键执行步骤(核心窗口阶段)
-
窗口扩张至
[31, 89](对应香蕉55、56在窗口内):- 当
r移动到55时,sum=1(≤2),继续扩张; r移动到56时,sum=2(≤2),此时窗口包含55、56两个香蕉(刚好用完2次魔法);- 继续扩张
r到89,窗口内香蕉数仍为2(≤2),窗口长度为89-31+1=59,ans更新为59; - 当
r移动到90时,sum=3(>2),触发左指针收缩:左指针从31右移,直到移出55(sum减为2),窗口重新合法。
- 当
-
最终
ans保留最大值59,与样例输出一致。
五、代码复杂度分析
1. 时间复杂度
- 滑动窗口的
l和r指针均最多遍历L次(L≤1e7),总循环次数为O(L)。 - 输入香蕉位置的循环为
O(n)(n≤1e5),可忽略。 - 整体时间复杂度:
O(L),在L≤1e7的范围内可通过所有测试用例。
2. 空间复杂度
- 数组
a的大小为1e7+10,每个元素为int型(4字节),总占用约40MB,符合内存限制。 - 其余变量为常数级,空间复杂度:
O(L)。
六、代码补充说明
1. 正确性保障
- 窗口合法条件(
sum≤m)确保区间内香蕉可全部转为苹果,窗口长度即为连续苹果段长度。 - 每次扩张窗口前更新
ans,确保不会遗漏当前窗口的最大长度。
2. 边界情况处理
- 当
m≥n时:所有香蕉可转为苹果,窗口最终会覆盖[1, L],ans=L,正确。 - 当
n=0时:无香蕉,sum=0,窗口覆盖[1, L],ans=L,正确。 - 当
m=0时:窗口内不能有香蕉,会自动收缩为仅包含苹果的最长区间,正确。
3. 可优化点(非必要)
- 数组
a可改用bool型(1字节),将空间占用降至10MB左右。 - 无需存储所有位置,可通过香蕉位置的滑动窗口优化时间复杂度至
O(n)(适合L极大的场景),但用户代码的逻辑已能正确解决问题。
- 输入:第一行
- 1
信息
- ID
- 5492
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 30
- 已通过
- 11
- 上传者