[JZOJ4944]Monument

来源:互联网 发布:ubuntu开机显示grub 编辑:程序博客网 时间:2024/04/29 08:57

题目大意

n个人在一条无穷的数轴上,一开始第i个人在pi上,从零时刻开始以每秒vi的速度移动。
现在你最多可以删除K个人,最大化T使得在前T时间内不存在任意两个人曾经相遇(位置相同即相遇,包括追及)。

1kn105,|pi|,|vi|109


题目分析

首先我们可以想到二分答案。那么怎么判定答案t是否可行呢?
可以发现,两个人没有相遇当且仅当在零时刻两人的相对顺序和t时刻一致。
那么我们删掉最少的人=保留最多的人使得这些相对顺序不发生变化。
那可以一开始将所有人按照pi排序,然后判定时计算每个人的位置,做一个最长上升子序列就可以得到最多能保留的人数。
A为二分上界,然后就O(nlognlogA)解决问题了。


代码实现

使用lower_bound来实现LIS真短!

#include <algorithm>#include <iostream>#include <cfloat>#include <cstdio>#include <cctype>using namespace std;typedef long double db;int read(){    int x=0,f=1;    char ch=getchar();    while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();    while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();    return x*f;}const db INF=2e+9;const db EPS=1e-5;const int N=100050;int v[N],p[N],kth[N];db f[N],x[N];db ans;int n,K;bool judge(db t){    for (int i=1;i<=n;i++) x[i]=1.0*v[kth[i]]*t+1.0*p[kth[i]];    for (int i=1;i<=n;i++) f[i]=DBL_MAX/3;    f[0]=-DBL_MAX/3;    int len=0;    for (int i=1;i<=n;i++)    {        int id=lower_bound(f,f+len+1,x[i])-f;        f[id]=x[i],len=max(len,id);    }    return n-len<=K;}void binary_search(){    for (db l=0.0,r=INF,mid;r-l>EPS;)    {        mid=(l+r)/2.0;        if (judge(mid)) l=(ans=mid)+EPS;        else r=mid-EPS;    }}bool cmp(int x,int y){return p[x]<p[y];}int main(){    freopen("monument.in","r",stdin),freopen("monument.out","w",stdout);    n=read(),K=read();    for (int i=1;i<=n;i++) p[i]=read(),v[i]=read(),kth[i]=i;    sort(kth+1,kth+1+n,cmp);    binary_search();    if (judge(ans+1.0)) printf("Forever\n");    else printf("%.4lf\n",(double)ans);    fclose(stdin),fclose(stdout);    return 0;}
0 0
原创粉丝点击