城市里有3000条横向的道路和3000条纵向的道路,分别从1开始编号知道3000,。相邻两条平行道路的间距为1。
我们用(x,y)表示第x号横向道路和第y号纵向道路。N个需要送快递的点坐落在这些交点上。小Q只能沿着这些道路送快递,而且只能在道路的交叉点改变方向。
接下来的M天,小Q每天都要从指定的地方出发将快递送往N个点。幸运的是,犇犇老师教了小Q分身大法,可以消耗s点法力值制造一个可以走s距离的分身,但是每个分身只能搬得动一件快递。小Q不想自己去送快递,于是他想请你帮忙计算,每一天他最少需要多少法力值才能让分身们帮他送完所有的快递。
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,表示需要送快递的点数N(N<=200000)和小Q送快递的天数M(M<=200000)。
接下来的N行,每行包含两个正整数xi(xi<=3000)和yi(yi<=3000),表示需要送快递的点的坐标。
接下来的M行,每行包含两个正整数ai(ai<=3000)和bi(bi<=3000),表示当天送快递的出发点。
对于每一天,在单独的一行输出一个整数,表示当天送完快递最少需要的法力值
3 3
5 5
5 10
10 5
1 1
5 5
10 10
34
10
20
方案一:在每一天,以出发点为坐标中心,遍历所有收货点进行路径长度的计算
评价一:这样的算法规模太大,时间复杂度为O(MN),故该方案可以直接抛弃
方案二:在输入收货点的时候,计算所有的点与原点的路径长度,最后根据每天的出发点,减去与原点之间的差值,算出最少小号的法力
评价二:这样的算法规模得到优化,时间复杂度为O(M+N),但该算法存在缺陷,所有的收货点必须位于出发点的同一象限之内
方案三:在输入收货点的时候,计算所有的点与原点的的路径长度。接着预计算一个距离表(具体意义看下文),最后通过某条公式直接算出最少小号的法力
评价三:这样的算法时间复杂度为O(M+N),兼容了多个象限上的路程问题,推荐使用
我想你们一定会很好奇,我是怎么想到这第三个方案的。首先,直觉告诉我,这个最短路径,肯定与所有点到原点的路程之和存在一定关系。那么,现在就让我们见证下Excel强大的分析功能(为方便说明,下图只抽取y轴上的距离进行计算)
从图中我们可以发现,计算距离与实际距离是相同的,而且距离偏差存在一定的规律可巡,证明该条公式是存在的。
这是我的猜想:法力消耗=sum-p*count+d[p],因为不知道怎么证明
sum:一个整数,表示所有收货点在某一方向距离原点的路径长度
p:一个整数,表示送货点在某一方向上的位置
count:一个整数,表示收货点的数量
d:一个数组,下标代表在某一方向上的位置,表示在一个方向中,每个点距离所有收货点的距离补偿
仔细研究这个d数列可以发现,他是一个由偶数组成的数列,并且在每当越过一个收货点,距离偏差都会加上2,同时这个距离偏差是可以累加的。有以下两条公式可以参考一下:
距离偏差=距离偏差+当前所在位置跨越的点数*2。
距离补偿[n]=距离补偿[n-1]+当前距离偏差
关于这个距离补偿的数列,我不清楚存在该结构的原因,而且不清楚距离偏差为什么那样计算。如果有知道其中原因的,麻烦告知
#include
#include
由于是昨天刚出的编程题,当时只想到第二个方案,只过了30%的数据,今天才想出最好的方案。但是考试链接已失效,我也没法验证这个代码是否能AC,欢迎大佬们批评指正