题目链接

找单步跳跃的终点,相当于找到最小的,使得内石头的个数

对于每个

  • 左侧石头个数为,右侧石头个数为
  • 考虑取个左侧石头和个右侧石头
  • 此时取的所有石头中,最左侧石头和最右侧石头的距离为
  • 是一个单峰函数,所以可以用三分法求符合要求的
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int inf = 0x3f3f3f3f;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n, k;
    ll m;
    cin >> n >> k >> m;

    vector<ll> A(n);

    unordered_map<ll, int> mp;
    for (int i = 0; i < n; ++i){
        cin >> A[i];
        mp[A[i]] = i;
    }

    vector<int> B(n, 0);

    auto f = [&](int idx, int lcount, int rcount){
        ll res = 0;
        if (lcount){
            res = max(res, A[idx] - A[idx - lcount]);
        }
        if (rcount){
            res = max(res, A[idx + rcount] - A[idx]);
        }
        return res;
    };

    for (int i = 0; i < n; ++i){
        int left = i;
        int right = n - 1 - i;

        int l = max(0, k - right);
        int r = min(k, left);

        while (r - l > 3){
            int step = (r - l) / 3;

            int lmid = l + step;
            int rmid = r - step;

            ll f1 = f(i, lmid, k - lmid);
            ll f2 = f(i, rmid, k - rmid);

            if (f1 <= f2){
                r = rmid;
            }
            else{
                l = lmid;
            }
        }

        ll dist = inf;

        for (int lc = l; lc <= r; ++lc){
            int rc = k - lc;
            dist = min(dist, f(i, lc, rc));
        }

        if (mp.count(A[i] - dist)){
            B[i] = mp[A[i] - dist];
        }
        else{
            B[i] = mp[A[i] + dist];
        }

    }

    vector<int> res(n);
    iota(res.begin(), res.end(), 0);

    for (int bit = 0; bit < 60; ++bit){
        if ((m >> bit) & 1){
            vector<int> newres(n);
            for (int i = 0; i < n; ++i){
                newres[i] = B[res[i]];
            }
            swap(res, newres);
        }

        vector<int> newB(n);
        for (int i = 0; i < n; ++i){
            newB[i] = B[B[i]];
        }
        swap(B, newB);
    }

    for (int i = 0; i < n; ++i){
        cout << res[i] + 1 << " \n"[i == n - 1];
    }
}