H. 鸡哥的 AI 驾驶 题解(二分+思维)

题目链接

题目思路

容易想到本题要求的最晚安全时间可以用二分的方式寻找。

对于两种不同型号的车,如果他们的相对位置发生了改变,那么就发生了碰撞。

因此,每辆车移动的最大范围就是他两边相同型号车的范围。

这句话的意思就是最开始按照位置排完序之后现在型号为 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;
}

posted @ 2021-09-10 15:39  hunxuewangzi  阅读(196)  评论(2编辑  收藏  举报