题目链接
题目思路
容易想到本题要求的最晚安全时间可以用二分的方式寻找。
对于两种不同型号的车,如果他们的相对位置发生了改变,那么就发生了碰撞。
因此,每辆车移动的最大范围就是他两边相同型号车的范围。
这句话的意思就是最开始按照位置排完序之后现在型号为 1 1 2 2 2 1 1
那么前两个车可以随意位置
第3-第5个车可以随意位置
最后两个车可以随意位置
二分时间,按新位置排序,如果某个时间有车辆超出了它的最大移动范围,那么就发
生了碰撞,这个检查可以在 (O(n logn)) 的时间内完成。
当然还有许多其他的方法来进行 check。
check的时候要注意相等坐标的情况要特判
复杂度:(O(n log^2n))
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=998244353,lim=300;
const double eps=1e-6;
int n,k;
int l[maxn],r[maxn];
pair<ll,int> pa[maxn];
struct node{
int p,v,t,id;
}a[maxn];
bool cmp(node a,node b){
return a.p<b.p;
}
bool check(ll x){
for(int i=1;i<=n;i++){
pa[i]={a[i].p+a[i].v*x,i};
}
sort(pa+1,pa+1+n);
for(int i=1;i<=n;i++){
if(i!=1&&pa[i].fi==pa[i-1].fi&&pa[i].se!=pa[i-1].se) return 0;
if(l[pa[i].se]>i||i>r[pa[i].se]) return 0;
}
return 1;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i].p>>a[i].v>>a[i].t;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
if(a[i].t==a[i-1].t){
l[i]=l[i-1];
}else{
l[i]=i;
}
}
for(int i=n;i>=1;i--){
if(a[i].t==a[i+1].t){
r[i]=r[i+1];
}else{
r[i]=i;
}
}
ll l=0,r=1e10,ans=-1;
while(l<=r){
ll mid=(l+r)/2;
if(check(mid)){
l=mid+1;
ans=mid;
}else{
r=mid-1;
}
}
if(ans==1e10) ans=-1;
cout<<ans;
return 0;
}