[USACO14DEC] Cow Jog G

洛谷[USACO14DEC] Cow Jog G

题目大意

n n n头奶牛,每头奶牛都有一个不同的初始位置和不同的跑步速度。

整个跑道被分为若干条赛道,比赛时间为 T T T分钟,需要保证在同一时刻,不可能在同一条赛道的同一个位置上存在两头相同的奶牛。

保证输入时奶牛按起点升序排列。

1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1n105


题解

我们来探讨一下在同一赛道上的两头奶牛在什么情况下不会发生碰撞。

设有两头奶牛,起点分别为 s 1 , s 2 ( s 1 < s 2 ) s_1,s_2(s_1s1,s2(s1<s2),速度分别为 v 1 , v 2 v_1,v_2 v1,v2

v 1 < v 2 v_1v1<v2时,因为第二头奶牛起点较后,速度较快,所以始终领先前一头奶牛,不会相撞。

v 1 > v 2 v_1>v_2 v1>v2时,设两头奶牛从开始到相撞的时间为 t t t,则 s 1 + t ⋅ v 1 = s 2 + t ⋅ v 2 s_1+t\cdot v_1=s_2+t\cdot v_2 s1+tv1=s2+tv2,解得 t = s 2 − s 1 v 1 − v 2 t=\dfrac{s_2-s_1}{v_1-v_2} t=v1v2s2s1。当 t > T t>T t>T时,两头奶牛不会相撞。 t > T t>T t>T,即 s 2 − s 1 v 1 − v 2 > T \dfrac{s_2-s_1}{v_1-v_2}>T v1v2s2s1>T,整理得 s 2 + v 2 ⋅ T > s 1 + v 1 ⋅ T s_2+v_2\cdot T>s_1+v_1\cdot T s2+v2T>s1+v1T,也就是第二头奶牛的终点在第一头奶牛的终点之后。

我们发现,如果要满足不会相撞,那起点在后的奶牛,终点应该在起点在前的奶牛的后面。

因为数据中奶牛按起点升序排列,所以我们可以将奶牛依次放入赛道。对于每头奶牛,在目前已有的赛道中选择最后一头奶牛在满足终点小于当前枚举到的奶牛的情况下终点最后的赛道。如果没有满足条件的赛道,则新开一个赛道。根据贪心的思想,这种方法时最优的。

用二分在已有赛道中找到满足上述要求的赛道,然后加入新的奶牛。因为这是满足条件的终点最后的赛道,所以加入新的终点之后这条赛道的最后的终点还是比前一条赛道的前面(也就是说赛道的最后的终点位置从前到后是单调递减的),所以更改后不需要对赛道的顺序进行修改。

时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)

code

#include
using namespace std;
int n,h1;
long long t,x,y,b[100005],h[100005];
int main()
{
	scanf("%d%lld",&n,&t);
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&x,&y);
		b[i]=x+t*y;
	}
	h[++h1]=b[1];
	for(int i=2,l,r,mid;i<=n;i++){
		l=1;r=h1;
		while(l<=r){
			mid=l+r>>1;
			if(h[mid]<b[i]) r=mid-1;
			else l=mid+1;
		}
		if(r==h1) ++h1;
		h[r+1]=b[i];
	}
	printf("%d\n",h1);
	return 0;
}

你可能感兴趣的:(题解,题解)