P4998 信号站
Posted mysh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4998 信号站相关的知识,希望对你有一定的参考价值。
题目背景
扶贫行动来到了Q村,扶贫队准备在Q村修筑信号站,让Q村不再“远离尘世”,让人们获得丰富的外界信息。
题目描述
Q村非常非常Qiong,整个村只有一条路。在这条路上,有N户人家,因为条件有限,所以一个点上可能有多户人家。因为山区运输条件落后,所以扶贫队只能修筑k个信号站,并且他们希望各电站的不合理值之和最小。信号站的不合理值是指该信号站到每户人家的距离之和。
扶贫队善于修筑电站,但是他们不擅长选址~~(因为数学不好QwQ)~~,他们希望你>>编程高手,来帮助他们选择修筑信号站的最佳地点,使得k个信号站的不合理值最小。
距离求解方法:若某信号站的坐标为x,某户人家的坐标为y,那么该信号站与该人家的距离为|x-y|(即取绝对值)。
数据保证人家数大于信号站数。放置信号站的位置坐标必须为整数。一个位置上只能放一个信号站。
输入格式
共2行,
第一行,读入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次,感觉已经把可能会错的地方都试了一遍)
如果还找不到思路,可以先看一下这篇题解,我觉得原作者已经将做法讲得很清楚了,但配合本题解食用更加。
Wrong 1
向两边扩展时没有将两个指针移动(这个应该除了我没人错了)
解决方案:移动
Wrong 2
没考虑负数
解决方案:这个问题有两个解决方案
方案1(建议)
将全体加上1e6(但数组也要相应扩大)
方案二
在计算时对负数进行特判(比较麻烦一点,直接加简单)
Wrong 3
没开long long
解决方案:开long long(两年oi一场空,一场long long见祖宗)
Wrong 4
数组开小(或上限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 ",ans); return 0; }
以上是关于P4998 信号站的主要内容,如果未能解决你的问题,请参考以下文章
Django基础---web框架 和 django 介绍3 --model --form---跨站请求---cookie--session--分页--缓存--信号