一开始看错了题目 以为一个城市只能算一次(瞎子视力
然后得出一个结论最多折返一次 然后计算 然后wa
wa只会看样例才发现 一个城市能多次到达 那么m够大的话最后一定变成了在i到i+1之间来回 那么我们就枚举每个区间 是否正确?
错了然后苦思 然后看题解(后面的情况没想到啊啊啊
因为还有个问题没有考虑 我们本身的p位置是在两个城市之间 按照之前思路的话
是一直向着一路走 但有可能向另一边第一个走一个来回的距离小于后面重复走的区间的距离
有人说这样我们可以向另一边走两个等多个 我们可以证明 当你向另一边走多个都小于这个区间的话 那么这种情况就在之前或者之后的循环中经历(因为走了大于等于一个区间了) 这种情况是个伪特例
于是代码就出来了
#include <bits/stdc++.h> #define ll long long ll const N=1e5+5; ll const INF=1e18; using namespace std; ll t,n,m,p,pos[N]; int main() { scanf("%lld",&t); while(t--) { scanf("%lld%lld%lld",&n,&m,&p); for(int i=1;i<=n;++i)scanf("%lld",&pos[i]); ll ans=INF; ll k=lower_bound(pos+1,pos+1+n,p)-pos-1;///<p位置的序号 for(int i=1;i<n;++i){///枚举从p到i i i+1 区间 if(i<=k) { if(k-i+1>m)continue;///从p位置到i超过m个城市 ll x=m-(k-i+1),dis=p-pos[i]; ans=min(ans,dis+x*(pos[i+1]-pos[i])); if(x&&k+1<=n)ans=min(ans,(pos[k+1]-p)*2+dis+(x-1)*(pos[i+1]-pos[i]));///验证向右走一步是否小一些 } else { if(i-k>m)continue;///从p位置到i超过m个城市 ll x=m-(i-k),dis=pos[i]-p; ans=min(ans,dis+x*(pos[i+1]-pos[i])); if(x&&k>=1)ans=min(ans,(p-pos[k])*2+dis+(x-1)*(pos[i+1]-pos[i]));///验证向左走一步是否小一些 } } cout<<ans<<endl; } return 0; }