I can only say that I'm too delicious. I really can't think of it at all.
If you simply want to find this collision combination, it is very difficult. So consider the overall situation. If two cars collide, the relative position of the two cars has changed. What we are looking for is that he must surpass the nearest left or right cars of different models, because if he wants to overtake, he must surpass the first one first and then the second one, then our task becomes to find that the relative positions of two cars of different models have changed for the first time at a certain time.
Then we can Two point answer , The criterion of two points is time.
We can first record the number of the first car before it that is different from its model and the first number after it in the L and R arrays, and then for each t, verify whether the car on his left appears later than him and whether the car on his right appears earlier than him.
Secondly, there is a clever way to find the left and right arrays. This is even more unexpected. I'm about to cry
L[r[1].id]=-1,R[r[n].id]=-1; for(int i = 2; i <= n ; i++){ if(r[i-1].p == r[i].p){ L[r[i].id]=L[r[i-1].id];/If the model is the same, they are the same L The array is the same } else{ L[r[i].id]=r[i-1].id;/Otherwise it's his subscript } } for(int i = n-1; i >= 1; i--){ if(r[i+1].p == r[i].p){ R[r[i].id]=R[r[i+1].id]; } else{ R[r[i].id]=r[i+1].id; } }
Then there is the selection of the check function
We can sort their current positions according to the size, and then traverse from front to back to verify whether the car on his left does not appear, or the car on her right appears, but there may be a special case, that is, they arrive at the same point at a certain time, but their relative position does not change. So you can use a vis to store whether it appears or not, and the po array to store the position of this point.
At the same time, the array po of recording positions here can be opened as long long or stored in map, otherwise it will explode
for(int i = 1; i <= n ; i++){ rr[i]=r[i]; rr[i].x+=t*rr[i].v; } sort(rr+1,rr+1+n); for(int i = 1; i <= n ; i++){ int pos1=L[rr[i].id],pos2=R[rr[i].id]; if(pos1 != -1){/So you don't have to think about it-1 Because consideration is meaningless, he is always established if(!vis[pos1]){/If they don't exist at all, they're over return true; } else{/If before him, but they are in the same position, they still surpass him if(po[pos1] == rr[i].x) return true; } } if(pos2 != -1){ if(vis[pos2]) return true; } vis[rr[i].id]=1;po[rr[i].id]=rr[i].x; }
Then, in the case of failure, we actually need to be as good as its maximum possible value. If there is no collision in this way, there will be no collision later. The limit is two different models of cars, one at - 1e9 with a speed of 1 and the other at 1e9 with a speed of 0. Then they need 2e9 in total, so it is more than enough to set 3e9. My habit is to maintain an endpoint. If the current time is feasible, it means that the answer is either the current time or earlier than the current time (because this question allows us to find the longest safe time) then the total output is collision time - 1
ll l=0,r=3e9+10; while(l<r){ ll mid=r+l-1>>1; if(check(mid)) r=mid; else l=mid+1; } if(r>=3e9+10) printf("-1"); else printf("%d",r-1);
So the total complexity is n*log(n)*log(n)
Finally, attach the complete code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> using namespace std; typedef long long ll; const int maxn = 1e5+10; struct node{ ll x,v,p,id; friend operator <(node x,node y){ return x.x<y.x; } }r[maxn],rr[maxn]; int n,m,a[maxn][2],L[maxn],R[maxn],vis[maxn],k1,k2; map<int,ll>po; bool check(ll t){ memset(vis,0,sizeof vis); po.clear(); for(int i = 1; i <= n ; i++){ rr[i]=r[i]; rr[i].x+=t*rr[i].v; } sort(rr+1,rr+1+n); for(int i = 1; i <= n ; i++){ int pos1=L[rr[i].id],pos2=R[rr[i].id]; if(pos1 != -1){ if(!vis[pos1]){ return true; } else{ if(po[pos1] == rr[i].x) return true; } } if(pos2 != -1){ if(vis[pos2]) return true; } vis[rr[i].id]=1;po[rr[i].id]=rr[i].x; }return false; } int main() { scanf("%d %d",&n,&m); for(int i = 1; i <= n ; i++){ scanf("%lld %lld %lld",&r[i].x,&r[i].v,&r[i].p); r[i].id=i; }sort(r+1,r+1+n); L[r[1].id]=-1,R[r[n].id]=-1; for(int i = 2; i <= n ; i++){ if(r[i-1].p == r[i].p){ L[r[i].id]=L[r[i-1].id]; } else{ L[r[i].id]=r[i-1].id; } } for(int i = n-1; i >= 1; i--){ if(r[i+1].p == r[i].p){ R[r[i].id]=R[r[i+1].id]; } else{ R[r[i].id]=r[i+1].id; } } if(m == 1){/In this way, it can be directly determined that it is impossible printf("-1");return 0; } ll l=0,r=3e9+10; while(l<r){ ll mid=r+l-1>>1; if(check(mid)) r=mid; else l=mid+1; } if(r>=3e9+10) printf("-1"); else printf("%d",r-1); return 0; }