【问题描述】
小沐最近迷上一款赛车游戏,游戏是这样滴!
游戏中给出n辆赛车和一条无限长的公路。每辆车均在道路上有各自不同的起点,也有各自的前进速度(赛车始终是匀速前进)。为了防止跑得快的车在超过跑得慢的车时发生碰撞,每局游戏前,小沐要把道路分成许多赛道,使得处在同一条赛道上的车在本局游戏中不会处在同一个位置。游戏一旦开始,车的赛道就不能再更换。
一局游戏会持续T分钟,在一局中,小沐能获得的金币数量与赛道的数目成反比(当然在某种赛道设计方案中,如果游戏中发生了碰撞事故,则相应的罚没金币数量也是与赛道数量成反比的)。
由于小沐还小,需要你来帮助进行赛道设计,以赢得尽量多的金币。
【输入格式】
输入的第1行包含两个2个整数n和T,他们的意义如题目描述。接下来n行,每行2个整数,表示赛车的初始位置s(米)和速度v(米/分钟)。数据以s递增的顺序给出。
【输出格式】
输出一个整数,表示在T分钟(包含第T分钟)的游戏中,至少需要多少条赛道。
【输入样例】
5 3
0 1
1 2
2 3
3 2
6 1
【输出样例】
3
【数据范围】
50%的数据满足:1<=n<=1000
100%的数据满足:1<=n<=100000,1<=T<=1000000000,0<=s<=1000000000 ,0
题解:
贪心,维护每条赛道上跑的最远的车的终点road[i],由于数据已按s排好序,所以直接按顺序考虑每辆车放于哪个赛道就行了
对于赛车i、j,当起点s[i] < s[i]且终点t[i]>t[j]时,可以判断i与j会相撞
对于第i辆车,当前j-1条赛道不能满足条件而第j条满足时,应放在第j条赛道并更新road[j]=t[i]
当没有赛道满足条件时,则单独放于新赛道中
可以发现road数组是单调递减的,于是用二分查找赛道
本来对于100%的数据,O(n^2)算法是过不了的,但是数据有随机性,ans最大在600左右,于是顺序查找水过。。。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int maxn=100005;
struct data{
ll s,t;
friend bool operator<(data a,data b){
if(a.s!=b.s) return a.s<b.s;
return a.t<b.t;
}
}car[maxn];
int cc=0;
ll n,t,road[maxn];
ll in(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int main(){
freopen("racing.in","r",stdin);
freopen("racing.out","w",stdout);
n=in(),t=in();
ll s,v;
for(int i=1;i<=n;i++){
s=in(),v=in();
car[i].s=s,car[i].t=s+v*t;
}
sort(car+1,car+n+1);
bool ok;
for(int i=1;i<=n;i++){
ok=0;
for(int j=1;j<=cc;j++) if(car[i].t>road[j]){ //顺序查找是错的!错的!错的!懒得改二分而已
road[j]=car[i].t,ok=1;
break;
}
if(!ok) road[++cc]=car[i].t;
}
printf("%d",cc);
return 0;
}