专栏文章
题解:P14330 [JOI2021 预选赛 R2] 往返滑道 / Round Sugoroku
P14330题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minh2etj
- 此快照首次捕获于
- 2025/12/02 02:18 3 个月前
- 此快照最后确认于
- 2025/12/02 02:18 3 个月前
P14330 [JOI2021 预选赛 R2] 往返滑道 / Round Sugoroku题解
题目传送门
算法设计
- 核心优化思路 将 “逐秒移动” 转化为 “批量计算单次连续移动的距离”:
- 每次移动前,确定下一个触发反弹的目标(最近的未处理 # 或边界)
- 直接计算当前位置到目标的距离,累加为总时间,跳过中间逐秒计算
- 处理目标后更新方向和未处理 # 列表,重复至所有 # 处理完毕
- 数据结构与工具 存储 # 位置:收集所有初始 # 的 位置,排序后方便查找
- 二分查找:用函数"lower_bound" 快速定位 “当前方向上最近的未处理 #”,时间复杂度 ( 为 # 数量)
代码实现
CPP#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, a;
string s;
cin >> n >> a >> s;
vector<int> h;
for (int i = 0; i < n; ++i)
if (s[i] == '#') h.push_back(i + 1); // 转为1-based位置
int m = h.size();
sort(h.begin(), h.end());
long long t = 0;
int p = a, d = 1, l = 0, r = n + 1;
while (m) {
if (d == 1) { // 向右移动
auto it = lower_bound(h.begin(), h.end(), p);
int nh = (it != h.end()) ? *it : r + 1;
int np = min(nh, r);
t += np - p;
p = np;
if (p == r) d = -1;
else { h.erase(it); m--; d = -1; }
} else { // 向左移动
auto it = lower_bound(h.begin(), h.end(), p);
int nh = (it != h.begin()) ? *prev(it) : l - 1;
int np = max(nh, l);
t += p - np;
p = np;
if (p == l) d = 1;
else { h.erase(prev(it)); m--; d = 1; }
}
}
cout << t << '\n';
return 0;
}
复杂度分析
- 时间复杂度:
- 收集 # 位置:
- 排序 # 列表:
- 处理每个 #:每次二分查找
- 操作 ,因为每个 # 仅删除一次),总 ,故整体满足 的约束)
- 空间复杂度:,仅存储 # 位置的
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...