一开始以为要dp或者分类讨论什么的,搞得很麻烦;
后来发现可以倒着想:注意到每次可以运送k个货物,那么先不考虑回来,总路程就是分别从两边的端点开始,每次k个,作为每次分路程截至的点;容易发现如果不按照这种策略,那么端点一定要送一次,然后离端点比较近的一个点也要被送一次,这样总路程就比上述策略大了,具体的数学式子就不列了,反着这么一想应该是比较显然的;然后再考虑回到出发点,只要把之前的答案*2再减去绝对值最大的路程的那个点就行了,因为没说一定要回来嘛,最大值可以在之前维护送货的数组的时候维护一下,或者sort一下都行;
完整代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const ll mod=1e9+7;
ll a[200050];
ll b[200050];
int main(){
std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("cfsb.out","w",stdout);
int T;cin>>T;
while(T--){
ll n,k;cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
ll num=0;
for(ll i=1;i<=n&&a[i]<0;i+=k)b[++num]=-a[i];
for(ll i=n;i>=1&&a[i]>0;i-=k)b[++num]=a[i];
sort(b+1,b+num+1);
ll ans=0;
for(int i=1;i<=num;i++)ans+=2*b[i];
ans-=b[num];
cout<<ans<<endl;
}
return 0;
}