题解:P14330 [JOI2021 预选赛 R2] 往返滑道 / Round Sugoroku

· · 题解

P14330 [JOI2021 预选赛 R2] 往返滑道 / Round Sugoroku题解

题目传送门

算法设计
#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;
}
复杂度分析
  1. 时间复杂度:O(M \log M)
    • 收集 # 位置:O(N)
    • 排序 # 列表:O(M \log M)
    • 处理每个 #:每次二分查找 O(\log M)
    • vector$ $erase$ 操作 $O(1)$,因为每个 **#** 仅删除一次),总 $O(M \log M)
  2. 空间复杂度:(O(M),仅存储 # 位置的 vector