【题解】CF1591C

一开始以为要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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值