题目:
2248. 【2017.12.02普及组模拟】送快递
时间限制: 3000 ms 空间限制: 512000 KB题目描述
Petya和Vasya被聘为快递员。在工作日期间,他们将提供包裹到线上的不同点。根据公司的内部规定,包裹的交付必须严格按照一定的顺序进行。最初,Petya处于坐标s1的点,Vasya位于坐标s2的点,n个顾客所需访问的顺序位于点x1,x2,...,xn。
这些人预先同意他们谁将交付给哪些客户,然后他们的行为如下。当第i个客户端的包裹被交付时,两个快递员中的其中一个负责去送第i+1个。此时不送快递员的那个原地不动。即快递是严格按照顾客顺序一个个在送的,一个快递员在送的时候,另一个快递员是不动的。
由于要相互沟通,这些家伙有对讲机。对讲机的工作距离不是很远,所以Petya和Vasya想在送快递的时候,使得他们的最大距离尽可能低。帮助Petya和Vasya尽量减少他们之间的最大距离,遵守所有交货规则。
输入
第一行包含三个整数n,s1,s2(1≤n≤100000,0≤s1,s2≤10^9) - Petya和Vasya的送货数量和起始位置。
第二行包含n个整数x1,x2,...,xn - 客户坐标(0≤xi≤10^9),以便交货。
保证,在数字s1,s2,x1,...,xn中没有两个相等。
输出
只有一行一个正数,即最小可能的最大距离。
样例输入1
2 0 10
5 6
样例输入2
3 2 1
3 4 5
样例输入3
1 4 5
2
样例输出1
10
样例输出2
1
样例输出3
2
注意在第一个测试案例中,快递员之间的初始距离为10.这个值将是答案,例如,Petya可以执行两次交付,Vasya将保持在起点。
在第二个测试用例中,您可以通过以下方式进行最佳的操作:Vasya向第一个客户送货,Petya到第二个,最后,Vasya将包提供给第三个客户。按照这种交货顺序,快递员之间的距离不会超过1。
在第三个测试用例中,只有两种情况是可能的:如果单个包装的交付由Petya执行,则它们之间的最大距离为5 - 2 = 3.如果Vasya将提供包装,最大距离为4 - 2 = 2.后一种方法是最优的。
数据范围限制
对于20%的数据,n<=25
对于40%的数据, n<=100
对于60%的数据, n<=2000
对于100%的数据,n<=100000
题解:
100分:
首先我们二分答案,并判断二分得到的mid是否合法。
怎么判断呢?
还是我讲题时的那副图:
不难发现,第i层就是a[-1],a[i]; a[0],a[i]; a[1],a[i];…… a[i-1],a[i]。
事实上我们只存储合法的a[k],a[i]值,也就是说如果a[0],a[i]不合法,第i层就不会出现a[0],a[i]。
而a[k],a[i]合法的条件是abs(a[k]-a[i])<=mid且a[k],a[i-1]合法;
特殊地,如果k=i-1,即a[k],a[i-1]不存在,那么要使a[k],a[i]合法,要满足一下条件:
1、abs(a[k]-a[i])<=mid;
2、a[-1..k-1],a[k]中,至少有一个合法。
最后,如果我们做到第n层时还有东西合法,二分的mid就是合法的,反之,就是不合法的。
那么,怎么去实现呢?
实际上,这题的解法有很多种,但都是根据上述思路演变而来,只是实现方法的有所不同。
这题可以用平衡树(c++自带有set),但由于很多同学(包括我)不会用,所以我们尝试思考一下别的做法。
我们考虑一层一层来模拟。
但是很快就会发现如果mid合法,最坏的枚举效率是O(n^2)的。
也就是说只有六十分。
我们再继续想,按层模拟不行,是因为如果有合法的就一定得模拟到第n层。如果我们按列来模拟,只要有一列到得了第n层,后面的列都可以不用枚举了。
判断二分mid是否合法,实质就是判断是否至少有一个a[i],a[n]合法。
而前面已经讲了,如果 a[i],a[n]合法,则abs(a[i]-a[n])<=mid且a[i],[n-1]合法,而要a[i],[n-1]合法,则……可以看出这实际上是一个递推的过程。直到判断到a[i],a[i+1]的时候,abs(a[i]-a[i+1])<=mid且a[-1..i-1],a[i]中,至少有一个合法。
所以我们枚举a[i],a[n]是否合法,从最上面下来,一旦有一个不合法,就中断,且a[i],a[n]不合法。如果能够到达第n层,那么二分的mid是合法的。
我们还应记录下最深层的中断位置max,表示a[-1..max-1],a[max]至少有一个合法,如果i+1<=max那我们就继续看a[i+1],a[n]是否合法,反之,二分的mid是不合法的。
因为数据是随机构造,这个方法的时间复杂度还是很理想的。
用这种方法比用平衡树(c++自带set)快了整整500毫秒。