思路
最后的答案一定是再两点之间一直徘徊着走。
所以直接枚举,起始点一直往左走,然后再任意两点间徘徊。
枚举起点一直往右走然后再任意两点间徘徊。
考虑一下一种特殊的情况,就是我先往左走一个城市,然后一直往右走,或者先往右走一个城市,然后一直左走。
为什么会有这样的走法?比如先往左走一下,在一直往右走,那么容易得到左走那一部分的路径走了两次。
也就是说可能存在你右走要新去一个点的距离比这个大。所以宁愿走这个两倍的距离,虽然距离是两倍但走得相对于一直右走距离更短。
那么往右走一下,在一直往走左也是同理。
还有一种特殊情况。就是一直在起点左右两个城市一直来回徘徊。其实直观感觉上这样不是最优的,因为会下意识地认为走了两段的路程会比走一段大。这是不一定的。比如这样一组数据
4 10 100
1 99 101 10000
一直在99和101之间走肯定是最优秀的走法
想好这些情况,暴力枚举即可。。
这题快wa哭了,在起点左右的城市徘徊这个点没想到。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1 << 17];
int main()
{
    int t; cin >> t;
    while (t--)
    {
        ll n, m, p;
        cin >> n >> m >> p;
        for (int i = 1; i <= n; i++)  cin >> a[i];
        ll pos = lower_bound(a + 1, a + n + 1, p) - a;
        pos--;//找到起点左边最近的一个城市下标
        ll ans = 1e18;

        for (int i = 1; i < pos; i++)
        {
            int k = pos - i + 1;//从起点走到下标i的城市个数
            if (k <= m)
            {
                ans = min(ans, p - a[i] + (m - k) * (a[i + 1] - a[i]));//在下标i和下标i+1之间徘徊
                if (p < a[n-1] && m>k)//先往右走一个城市
                    ans = min(ans, p - a[i] + 2 * (a[pos + 1] - p) + (m - k - 1) * (a[i + 1] - a[i]));
            }
        }
        pos++;//起点右边第一个城市
        for (int i = pos; i < n; i++)
        {
            int k = i - pos + 1;///到下标i的经过的城市个数
            if (k <= m)
            {
                ans = min(ans, a[i] - p + (m - k) * (a[i + 1] - a[i]));//在下标i和下标i+1之间徘徊
                if (p > a[1] && m>k)//先往左走一个城市
                    ans = min(ans, a[i] - p + 2 * (p - a[pos - 1]) + (m - k - 1) * (a[i + 1] - a[i]));
            }
        }
        if (p > a[1] && p < a[n])//在起点左右两个城市徘徊
        {    //先走向距离较近的一个,然后接下来每次要多增加一个访问量,就要走两段距离和
            ans = min(ans, (m - 1) * (a[pos] - a[pos - 1]) + min(a[pos] - p, p - a[pos - 1]));
        }
        cout << ans << endl;
    }
    return 0;
}