题意:在一个数轴上,给出$N$个人的初始位置与速度(速度有方向),求最大的时间使得存在$N-K$个人在这一段时间内两两没有相遇。$1 \leq K \leq N \leq 10^5$
显然有二分性质,考虑二分答案,接着考虑check过程。
考虑先按照位置排序,然后我们能够发现:如果两个人能够相遇,那么它们的位置大小顺序就会发生变化(也就是产生一个逆序对)
然后就能够发现:最多的互相没有相遇的人在新的位置序列上体现为最长上升子序列,然后就能够通过$O(nlogn)$转移得到答案。
#include<bits/stdc++.h> #define ld long double using namespace std; inline int read(){ ; ; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = ; c = getchar(); } while(isdigit(c)){ a = (a << ) + (a << ) + (c ^ '); c = getchar(); } return f ? -a : a; } ; ; struct peo{ int pos , v; }now[MAXN]; ld minN[MAXN]; int N , K , cnt; bool operator <(peo a , peo b){ return a.pos < b.pos; } bool cmp(ld a , ld b){ return a + eps > b && a - eps < b; } bool check(ld mid){ cnt = ; ; i <= N ; i++){ ld t = now[i].pos + now[i].v * mid; , t - eps) - minN; ){ minN[k] = t; if(k > cnt) ++cnt; } } return cnt + K >= N; } int main(){ N = read(); K = read(); ; i <= N ; i++){ now[i].pos = read(); now[i].v = read(); } sort(now + , now + N + ); ld L = , R = 2e9 + ; minN[] = -1e30; while(R - L > eps){ ld mid = (L + R) / ; check(mid) ? L = mid : R = mid; } if(R > 2e9) puts("Forever"); else printf("%Lf" , L); ; }