博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 P3819 松江1843路
阅读量:6087 次
发布时间:2019-06-20

本文共 2800 字,大约阅读时间需要 9 分钟。

题目描述

涞坊路是一条长L米的道路,道路上的坐标范围从0到L,路上有N座房子,第i座房子建在坐标为x[i]的地方,其中住了r[i]人。

松江1843路公交车要在这条路上建一个公交站,市政府希望让最多的人得到方便,因此希望所有的每一个的居民,从家到车站的距离的总和最短。

公交站应该建在哪里呢?

输入输出格式

输入格式:

 

第一行输入L、N。

接下来N行,每行两个整数x[i]和r[i]。

 

输出格式:

 

一个整数,最小的每个人从家到车站的距离的总和。

 

输入输出样例

输入样例#1:
100 320 350 270 1
输出样例#1:
110
输入样例#2:
100 20 1100 10
输出样例#2:
100
输入样例#3:
10000000000 53282894320 3914394338332 9296932893249 1817823822843 4409322388365 623
输出样例#3:
5473201404068

说明

样例解释1

当建在坐标40的时候,所有人距离车站的距离总和为 |20−40|×3+|50−40|×2+|70−40|×1=110。

数据范围和约定

对于10%的数据,1≤N≤50,R[i]=1。

对于30%的数据,1≤N≤100,R[i]≤10,1≤L≤1000。

对于70%的数据,1≤N≤1000,R[i]≤100,1≤L≤10^6。

对于全部数据,1≤L≤10^10,1≤N≤10^5,0≤x[i]≤L,1≤r[i]≤1000

吐槽

  好久没做在洛谷被标成“普及+/提高”难度的题了,这题难度被标高了……

  cmath里的abs简直就是一个大坑,当传过去的参数为long long型的时,返回值依然是int!!!

  因为这个我WA90分,整整两次!

  对long long取绝对值要algorithm里的std::abs才行,再或者就手写……

解题思路

中位数的思路

  题目原型是输油管道,在,出题人说洛谷7月月赛题目都是改编题果然不假。

  把每个人所在的位置记录下来,排成一个数列,那么公交站的位置就是这个数列的中位数所在位置。为什么是中位数呢?可以参考输油管道这题“深海鱼的眼泪”的题解.

我把他的题解改了一点——

  如果只有一个人,那么显然是越近越好。如果有两个人,那么显然是有以下三种情况:

    1.两个人都在公交站左边,那么这个时候的两个人到公交站的长度和肯定大于两个人的坐标之差。

    2.两个人都在公交站右边,和情况1是一样的

    3.两个人,一个在公交站右边,一个在公交站左边,那么两个人到公交车站的长度和就等于两个人的坐标之差。显然情况三是所要的路径和最短的设计情况。就是当公交站在两个人之间的任意位置时,人到公交车站长度之和都等于两个人的坐标之差,是最短的长度。

  那么将这个结论推广,当有n个人的时候——

    1.n是偶数 只要这n个人分布在公交站的两边,每边n/2个,那么就是距离之和最小的。

    2.n是奇数,只要将这n个人中,坐标最中间的(也就是中位数的那个)井不算,其余的偶数个人分布在公交站的两侧,这个时候移动公交站,那么这n个人到公交车站长度之和就决定于那个没有算的人了,因为其余的井的距离之和是固定了的,这个时候只要公交站最接近中间那个人就好了。

  也就是说,公交车站的位置就是最中间的那个人(或中间的区间)。

  将各个人的坐标排序,再取 n/2+1 的位置,即最中间的位置。最后统计答案即可。

三分的思路

  设f(x)为公交站设在x处时所有人到公交站距离之和,那么有可能f(x)在[1,L]上很有可能只有一个极小值(我不会证,但这个思路可以通过所有数据点,耗时为上面那个思路的一半),那个极小值就是答案。求那个极小值就能用三分法了。这个思路来自洛谷讨论区,下面的代码也是他的。

源代码

中位数思路的代码

#include
#include
struct house{ long long x,num; bool operator < (const house & a) const{ return x
>1)+1,pos; for(int i=1;i<=n;i++) { s+=h[i].num; if(s>=mid) { pos=h[i].x; break; } } long long ans=0; for(int i=1;i<=n;i++) ans+=std::abs(h[i].x-pos)*h[i].num; printf("%lld",ans); return 0;}

三分的代码

#include 
#include
typedef long long LL;static const int maxm = 2e6 + 10;static const LL INF = 1LL << 62;LL r[maxm],x[maxm],A[maxm];LL L,ans,mind = INF;LL n;LL abs(LL x){ return x > 0 ? x : -x;}LL f(LL D){ LL ret = 0; for(LL i = 1;i <= n;i++) ret += abs(D * r[i] - x[i] * r[i]); return ret;}int main(){ scanf("%lld%lld",&L,&n); for(LL i = 1;i <= n;i++) scanf("%lld%lld",&x[i],&r[i]); LL l = 0,r = L; while(l <= r){ LL mid = (l + r) >> 1; LL mmid = (mid + r) >> 1; if(f(mid) < f(mmid)) ans = mid,r = mmid - 1; else ans = mmid,l = mid + 1; } for(LL i = ans - 100;i <= ans + 100;i++) mind = std :: min(f(i),mind); printf("%lld\n",mind); return 0;}

 

转载地址:http://ahvwa.baihongyu.com/

你可能感兴趣的文章
unity将object[]或者string对象转换成枚举enum
查看>>
以太坊系列之六: p2p模块--以太坊源码学习
查看>>
使用scikit-learn解决文本多分类问题(附python演练)
查看>>
2018 年最值得关注的 JavaScript 趋势
查看>>
什么是区块链?超级账本 Brian Behlendorf 从五个方面教你认识
查看>>
Linux中的帮助功能
查看>>
针对Android的Pegasus恶意软件版本和针对iOS的有什么不同?
查看>>
全局探色器
查看>>
Hive Export和Import介绍及操作示例
查看>>
http://mongoexplorer.com/ 一个不错的 mongodb 客户端工具。。。
查看>>
上传jar包到nexus私服
查看>>
Why Namespace? - 每天5分钟玩转 OpenStack(102)
查看>>
Project:如何分析项目中的资源分配情况
查看>>
HDU 4803 Poor Warehouse Keeper (贪心+避开精度)
查看>>
小错误汇总
查看>>
Spring源码系列 — Envoriment组件
查看>>
java正则表达式去除html标签,Java中正则表达式去除html标签
查看>>
使用Cobbler批量部署Linux操作系统
查看>>
zabbix企业应用之服务端与客户端的安装
查看>>
实例讲解遗传算法——基于遗传算法的自动组卷系统【理论篇】
查看>>