1 条题解

  • 1
    @ 2025-12-31 23:59:59

    暴力:一步一步往后走,累计L使用就行

    稍微好一些:二分去找一步最远

    那我们能不能一步多走点,这个可以联想??????=》倍增的去求f[i][j]表示从i出发走j步到达的最远点。

    你的一小步,本题的一大步!!!

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 100000 + 5;
    const int LOG = 20; // 2^20 > 1e6,覆盖 N=1e5 绝对够
    
    int n, L, q;
    int x[MAXN];
    int dp[MAXN][LOG]; // dp[i][k]:从 i 出发走 2^k 天能到达的最远下标
    int pw2[LOG];
    
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        cin >> n;
        for (int i = 1; i <= n; ++i) cin >> x[i];
        cin >> L >> q;
    
        // 预处理 2^i
        pw2[0] = 1;
        for (int i = 1; i < LOG; ++i) pw2[i] = pw2[i - 1] << 1;
    
        // dp[i][0]:两指针求“从 i 出发一天内能到的最远点”
        int t = 1;
        for (int i = 1; i <= n; ++i) {
            if (t < i) t = i;
            // 注意判断顺序,先 t<n,再访问 x[t+1]
            while (t < n && x[t + 1] - x[i] <= L) ++t;
            dp[i][0] = t; // 至少 i 自己;若能往右就到 t
        }
    
        // 倍增
        for (int k = 1; k < LOG; ++k) {
            for (int i = 1; i <= n; ++i) {
                dp[i][k] = dp[ dp[i][k - 1] ][k - 1];
            }
        }
    
        // 处理询问
        while (q--) {
            int a, b; cin >> a >> b;
            if (a > b) swap(a, b);  // 只考虑从左到右
    
            int cur = a, ans = 0;
            // 从大到小尝试跳 2^i 天,保持 dp[cur][i] < b
            for (int i = LOG - 1; i >= 0; --i) {
                if (dp[cur][i] < b) {
                    ans += pw2[i];
                    cur  = dp[cur][i];
                }
            }
            cout << ans + 1 << '\n'; // 最后一步跳到 >= b
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    15
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    30
    已通过
    13
    上传者