一开始看成每个城市只能算一次,然后就愉快的wa了呢。
然后才看到可以反复在两个城市间走。
贪心的想如果m足够大那么最后一定是在两个城市间来回走。
所以我们可以枚举是在哪两个城市间走。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
#define PB push_back
#define INFL 0x3f3f3f3f3f3f3f3f

void solve()
{
    int n,m,p;
    scanf("%d%d%d",&n,&m,&p);
    vl pos(n,0ll);
    for(auto &i:pos) scanf("%lld",&i);
    vl left,right(1,0);//左边的点距原点的距离和右边的点距原点的距离 
    for(auto i:pos)
    {
        if(p>=i) left.PB(p-i);
        else right.PB(i-p);
    }
    left.PB(0);
    reverse(left.begin(),left.end());

    int num_l=left.size()-1,num_r=right.size()-1;
    //左边点的个数和右边点的个数 

    ll minv=INFL;
    if(m==1)//特判 
        minv=min(num_l?left[1]:INFL,num_r?right[1]:INFL);

    for(int i=1;i<num_l;i++)//枚举左边的 
    {
        if(i>m) break;
        minv=min(minv,left[i]+(m-i)*(left[i+1]-left[i]));
        if(i<m&&num_r) 
            minv=min(minv,left[i]+2*right[1]+(m-i-1)*(left[i+1]-left[i]));
    }

    for(int i=1;i<num_r;i++)//枚举右边的 
    {
        if(i>m) break;
        minv=min(minv,right[i]+(m-i)*(right[i+1]-right[i]));
        if(i<m&&num_l) 
            minv=min(minv,right[i]+2*left[1]+(m-i-1)*(right[i+1]-right[i]));
    }

    if(num_l&&num_r)//枚举一左一右 
    {
        ll &x=left[1],&y=right[1];
        minv=min(minv,min(x,y)+(m-1)*(x+y));
    }

    printf("%lld\n",minv);
}


int main()
{
    int t;
    scanf("%d",&t);
    while(t--) solve();
    return 0;
}