浙大校赛--G(贪心)

G postman

思路:

快递员肯定要从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;
} 

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/89321892