noi.ac 小W、小J和小Z
#8. 小w、小j和小z
小z告诉小w了这样一道送分题。
在数轴上有nn个小人,第ii个人现在在pipi位置,速度是vivi(速度的正负代表不同的方向)。如果某一时刻两个人在同一位置,那么就会发生碰撞。
如果现在小j可以使用能力,使得其中kk个人凭空消失,那么最多会有多长时间内,没有任何两个人会碰撞呢?
输入格式
一行两个整数 nn和kk。
接下来 nn行,每行两个整数pi,vipi,vi,表示每个人的初始位置和速度。
输出格式
如果时间是无限长,输出Forever, 否则输出一个实数表示答案,答案误差小于10−310−3即可。
样例一
input
4 1 1 1 3 -1 5 2 7 -2
output
1.00
样例二
input
4 2 1 1 3 -1 5 2 7 -2
output
Forever
数据范围和约定
本题采用捆绑测试,对于全部数据,1≤k≤n≤105;|pi|,|vi|≤109.1≤k≤n≤105;|pi|,|vi|≤109.
子任务编号 | 分值 | nn | kk |
---|---|---|---|
1 | 10 | ≤20≤20 | ≤n≤n |
2 | 20 | ≤200≤200 | ≤10≤10 |
3 | 15 | ≤n≤n | |
4 | 15 | ≤2000≤2000 | ≤10≤10 |
5 | 20 | ≤n≤n | |
6 | 20 | ≤105≤105 |
时间限制:2s2s
空间限制:256MB
思路:二分+ 最长上升子序列
时间复杂度O(nlogn*logn)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 #define F(i,a,b) for(int i=a;i<=b;i++) 5 #define D(i,a,b) for(int i=a;i>=b;i--) 6 #define ms(i,a) memset(a,i,sizeof(a)) 7 #define LL long long 8 9 int inline read(){ 10 int x=0,w=0; char c=getchar(); 11 while (c<'0' || c>'9') w+=c=='-',c=getchar(); 12 while (c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); 13 return w? -x: x; 14 } 15 16 int const maxn=100003; 17 double const eps=1e-8; 18 19 int n,k; 20 double b[maxn]; 21 struct people{ 22 double p,v,x; 23 bool operator < (const people & rhs) const{ 24 return p<rhs.p; 25 } 26 }a[maxn]; 27 28 int check(double mid){ 29 F(i,1,n) a[i].x=a[i].p+a[i].v*mid; 30 sort(a+1,a+n+1); 31 int t=0; 32 F(i,1,n){ 33 if(!t || b[t]<a[i].x) b[++t]=a[i].x; 34 if(t && fabs(b[t]-a[i].x)<eps) continue; 35 int h=upper_bound(b+1,b+t+1,a[i].x)-b; 36 b[h]=a[i].x; 37 } 38 return t+k>=n; 39 } 40 41 int main(){ 42 n=read(); 43 k=read(); 44 F(i,1,n) a[i].p=read(),a[i].v=read(); 45 double l=0,r=2e9; 46 F(i,1,100){ 47 double mid=(l+r)/2; 48 if (check(mid)) l=mid; 49 else r=mid; 50 } 51 if(fabs(r-2e9)<eps) printf("Forever\n"); 52 else printf("%0.5f\n",l); 53 return 0; 54 }