8.19 T2
Solution
把原来的pos排序,二分时间 t ,然后更新成新的pos’ ,再排序比较二者顺序是否完全相同。
疑难:对k不会处理 60 pts
std: 其实就差一点想到正解。。。我们对新的pos’ 求出最长上升子序列LIS , 然后 若序列长度>=n-k 就可行
(n^2暴力枚举任意两个点相撞时间,取min可以90分。。。痛心)
60分
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=50005;
int n,k;
double ans;
struct node{
double p,v;int id,rk;
}a[N],b[N];
bool cmp(node a,node b) {
return a.p==b.p?a.id<b.id:a.p<b.p;
}
bool check(double t) {
for(int i=1;i<=n;i++) {
b[i]=a[i];
b[i].p=a[i].p+a[i].v*t;
}
sort(b+1,b+1+n,cmp);
for(int i=1;i<=n;i++)
if(b[i].rk!=i) return 0;
return 1;
}
int main() {
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) {
scanf("%lf%lf",&a[i].p,&a[i].v);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
a[i].rk=i;
double l=0,r=1000000;
while(l<=r) {
double mid=(l+r)/2.0;
if(check(mid)) ans=mid,l=mid+0.00001;
else r=mid-0.00001;
}
if(ans>=999999) puts("Forever");
else printf("%.4lf",ans);
return 0;
}
100分
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long double ld;
const int N=1e5+5;
const ld eps=1e-4;
const ld inf=1e12;
int n,k;
struct node{
ld p,v;
int id;
bool operator < (const node &x) const {
return p<x.p;
}
}a[N],b[N];
inline void Max(int &x,int y) {if(x<y)x=y;}
int c[N];
int query(int x) {
int res=0;
for(int i=x;i;i-=i&(-i))
Max(res,c[i]);
return res;
}
void upd(int x,int v) {
for(int i=x;i<=n;i+=i&(-i))
Max(c[i],v);
}
inline bool check(ld t) {
memset(c,0,sizeof(c));
for(int i=1;i<=n;++i)
b[i].p=a[i].p+a[i].v*t,b[i].id=i;
sort(b+1,b+n+1);
for(int i=1;i<=n;++i)
a[b[i].id].id=i;
for(int i=1;i<=n;++i) {
int x=a[i].id;
int y=query(x-1);
upd(x,y+1);
}
return query(n)>=n-k;
}
int main() {
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
scanf("%Lf%Lf",&a[i].p,&a[i].v);
sort(a+1,a+n+1);
ld l=0,r=inf,mid;
while(abs(l-r)>eps*eps){
mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
if(abs(mid-inf)<=eps) puts("Forever");
else printf("%.4Lf",mid);
return 0;
}