小w、小j和小z
n个月没更了,现在学的东西很难,掌握不好,不敢更!
这个题目既不超范围又足够难想,反正我没想出来,很好的题目!
我发现noi.ac上的题目很不错!!!
-------------------------------------------------------------------------------------------------------------------
小z告诉小w了这样一道送分题。
在数轴上有n个小人,第ii个人现在在pi位置,速度是vi(速度的正负代表不同的方向)。如果某一时刻两个人在同一位置,那么就会发生碰撞。
如果现在小j可以使用能力,使得其中kk个人凭空消失,那么最多会有多长时间内,没有任何两个人会碰撞呢?
输入格式
一行两个整数 n和k。
接下来 n行,每行两个整数pi,vi,表示每个人的初始位置和速度。
输出格式
如果时间是无限长,输出Forever, 否则输出一个实数表示答案,答案误差小于10^−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≤10^5;|pi|,|vi|≤10^9.
_________________________________________________________________________________________
碰撞,可以选择让他消失。肯定先碰撞就让他消失。同时维护那么多点的位置?肯定是按照时间进行二分。消失如何处理?那就让他不消失,位置交换以后就是逆序,只要求最长上升子序列就好了!!
说起来简单,想的时候真的想不到!!!
所以正解就是二分答案+最长上升子序列。
注意刚开始的预处理!!!
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=100005; 4 int n,k; 5 struct node 6 { 7 int v,p; 8 }pt[maxn]; 9 bool cmp(node a,node b) 10 { 11 if(a.p<b.p)return 1; 12 if(a.p==b.p && a.v>b.v)return 1; 13 return 0; 14 } 15 int f[maxn]; 16 long double pos[maxn],low[maxn]; 17 bool pd(long double x) 18 { 19 for(int i=1;i<=n;++i)pos[i]=pt[i].p+pt[i].v*x,low[i]=3e9; 20 int ans=1; 21 low[1]=pos[1]; 22 for(int i=2;i<=n;++i) 23 { 24 if(low[ans]<pos[i])low[++ans]=pos[i]; 25 else low[upper_bound(low+1,low+ans+1,pos[i])-low]=pos[i]; 26 } 27 return n-ans<=k; 28 } 29 int main() 30 { 31 scanf("%d%d",&n,&k); 32 for(int i=1;i<=n;++i)scanf("%d%d",&pt[i].p,&pt[i].v); 33 sort(pt+1,pt+n+1,cmp); 34 int js=1; 35 for(int i=2;i<=n;++i) 36 { 37 if(pt[i].p==pt[js].p && pt[i].v==pt[js].v)k--; 38 else pt[++js]=pt[i]; 39 } 40 n=js; 41 long double l=0,r=3e9,ans; 42 while(r-l>0.0000001) 43 { 44 long double mid=(l+r)/2; 45 if(pd(mid))l=ans=mid; 46 else r=mid; 47 } 48 if(ans>2.9e9)printf("Forever"); 49 else printf("%.6lf",(double)ans); 50 return 0; 51 }