扶贫行动来到了Q村,扶贫队准备在Q村修筑信号站,让Q村不再“远离尘世”,让人们获得丰富的外界信息。
Q村非常非常Qiong,整个村只有一条路。在这条路上,有N户人家,因为条件有限,所以一个点上可能有多户人家。因为山区运输条件落后,所以扶贫队只能修筑k个信号站,并且他们希望各电站的不合理值之和最小。信号站的不合理值是指该信号站到每户人家的距离之和。
扶贫队善于修筑电站,但是他们不擅长选址~~(因为数学不好QwQ)~~,他们希望你>>编程高手,来帮助他们选择修筑信号站的最佳地点,使得k个信号站的不合理值最小。
距离求解方法:若某信号站的坐标为x,某户人家的坐标为y,那么该信号站与该人家的距离为|x-y|(即取绝对值)。
数据保证人家数大于信号站数。放置信号站的位置坐标必须为整数。一个位置上只能放一个信号站。
第一行,读入n,k,分别代表人家数和信号站数;
第二行,读入各户人家的坐标ai(保证为整数),用空格隔开。
仅一行,输出最小的不合理值之和。
7 2 1 1 2 2 3 3 4
13
####样例解释
在2和3的位置上放置信号站(方案不唯一)。
####数据范围
对于 70% 的数据,n,k≤10^3 ;
对于 100%的数据,n≤1000000,0≤ai≤10^6。
来写一下题解,帮助一些一直过不去但总体思路没错的同学(本人错了5次,感觉已经把可能会错的地方都试了一遍)
如果还找不到思路,可以先看一下这篇题解,我觉得原作者已经将做法讲得很清楚了,但配合本题解食用更加。
向两边扩展时没有将两个指针移动(这个应该除了我没人错了)
解决方案:移动
没考虑负数
解决方案:这个问题有两个解决方案
将全体加上1e6(但数组也要相应扩大)
在计算时对负数进行特判(比较麻烦一点,直接加简单)
没开long long
解决方案:开long long(两年oi一场空,一场long long见祖宗)
数组开小(或上限N定小)
解决方案:开大
放一下代码,经供参考。
————By chinaxjh
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=4000040;
int l[N],r[N];
long long le[N],ri[N],a[N];
long long n,m,ll,rr,now,ans;
long long cnt(long long k) {
return (llabs(k*l[k]-le[k])+llabs(k*r[k]-ri[k]));
}
int main() {
scanf("%lld%lld",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%lld",&a[i]);
a[i]+=1e6;
le[a[i]]+=a[i],ri[a[i]]+=a[i];
l[a[i]]++,r[a[i]]++;
}
sort(a+1,a+1+n);
for (int i=1; i<=N-10; i++) {
le[i]+=le[i-1];
l[i]+=l[i-1];
}
for(int i=N-10; i>=0; i--) {
ri[i]+=ri[i+1];
r[i]+=r[i+1];
}
now=rr=ll=a[(1+n)>>1];
for(int i=1; i<=m; i++) {
ans+=cnt(now);
if(cnt(ll-1)<cnt(rr+1)) {
ll--;
now=ll;
} else {
rr++;
now=rr;
}
}
printf("%lld\n",ans);
return 0;
}
原文:https://www.cnblogs.com/mysh/p/11832105.html