感受
似乎贪心就解决这个问题了,为什么当时比赛过得人这么少?


思路
首先,我们处在p位置,显然要么向左走到相邻的城市,要么向右走走到相邻的城市。
有一个不会证明但观察到的结论,从这两个位置走的话,只有四种可能。
可能1:一直向左走
可能2:一直向右走
可能3:一直向左走到第i个城市,然后再向右走到第i+1个城市,然后再向左走到第i个城市,然后再向右走到第i+1个城市...
可能4:一直向右走到第i个城市,然后再向左走到第i-1个城市,然后再向右走到第i个城市,然后再向左走到第i-1个城市...


观察的结论讲实话我也不会证明,坐等明天题解


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const ll inf = 1e18;
int n, m; ll p;
ll a[maxn];
ll solve1(int r, int m){
    if(r > n || r < 1) return inf;
    ll tmp = inf;
    for(int i = r; i <= n; i++){
        ll v = a[i] - a[r];///经过了i - r + 1座城市
        if(i == 1){
            if(m == 1) tmp = 0;
        }
        else{
            tmp = min(tmp, v + (a[i] - a[i - 1]) * max((m - (i - r + 1)), 0));
        }
    }
    return tmp;
}///r位置一直向右延伸
ll solve2(int l, int m){
    if(l < 1 || l > n) return inf;
    ll tmp = inf;
    for(int i = l; i >= 1; i--){
        ll v = a[l] - a[i];///经过了l - i + 1座城市
        if(i == n){
            if(m == 1) tmp = 0;
        }
        else{
            tmp = min(tmp, v + (a[i + 1] - a[i]) * max((m - (l - i + 1)), 0));
        }
    }
    return tmp;
}///l位置一直向左延伸
int main(){
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d%lld", &n, &m, &p);
        ll ans = inf;
        int l, r;
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
        }
        l = upper_bound(a + 1, a + n + 1, p) - a; r = l;
        l--;
        ans = min(ans, a[r] - p + solve1(r, m));
        ans = min(ans, p - a[l] + solve1(l, m));
        ans = min(ans, a[r] - p + solve2(r, m));
        ans = min(ans, p - a[l] + solve2(l, m));
        printf("%lld\n", ans);
    }
    return 0;
}