思路:
快递员肯定要从0点出发,如果在0点,就不用管,如果在正半轴或者负半轴就要算一下,计算正负半轴时可以对称考虑,
以正半轴为例,将所有存在的点按照到0的距离的大小从小到大排序,然后依次从后向前寻找,每过k个点找到一个点,就说明找到的这个到点,可以覆盖之前的k个点。然后用同样的方法考虑负半轴。
因为最后不用回到0点,所以再减去到0的距离最大的半轴的距离就好了。
注意:要考虑正,负半轴没有点的情况。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
set <LL> st1,st2;
vector <LL> v1,v2;
int main(void)
{
int T,i,j,n,k;
LL x,ans,tp1,tp2;
scanf("%d",&T);
while(T--){
ans = 0;
v1.clear();v2.clear();
scanf("%d%d",&n,&k);
for(i=0;i<n;i++){
scanf("%lld",&x);
if(x<0){
v1.push_back(abs(x));
}else if(x>0){
v2.push_back(x);
}
}
sort(v1.begin(),v1.end());
sort(v2.begin(),v2.end());
int t1 = v1.size(),t2 = v2.size();
tp1 = tp2 = 0;
if(t1>0){
for(i=t1-1;i>=0;i-=k) ans += v1[i]*2;
}
if(t2>0){
for(i=t2-1;i>=0;i-=k) ans+=v2[i]*2;
}
if(t1>0&&t2>0){
ans -= (v1[t1-1]>v2[t2-1]?v1[t1-1]:v2[t2-1]);
}
else if(t1>0&&t2==0){
ans -= v1[t1-1];
}
else if(t1==0&&t2>0){
ans -= v2[t2-1];
}
printf("%lld\n",ans);
}
return 0;
}