专栏文章
【题解】AT_cf_2015_morning_hard_h ありんこ
AT_cf_2015_morning_hard_h题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mir05u0h
- 此快照首次捕获于
- 2025/12/04 13:35 3 个月前
- 此快照最后确认于
- 2025/12/04 13:35 3 个月前
最小值最大确实是二分。一般是想二分 + 贪心。但是这道题套的是 DP。不能直接 DP 的原因是,它是一个 2D1D 的转移,然而代价函数长这样:
这个东笔者已经替你们思考了四个半小时了,它没有单调性、限制后的 1D 问题不是凸包、不满足四边形不等式。妥妥的 优化不了。
考虑回二分,二分能让我们得到什么?多出来一个最低代价 的限制。于是要保证选出的任意 满足 ,于是就可以分离变量了,强令 ,得到 ,再化一下变量就分离啦:,但要记住我们钦定了 。
在 DP 之前,还要证一个东西。
注意到如果某一小球 能对碰撞答案产生贡献,必然由和其相邻的小球碰撞产生。证明:
注意到如果某一小球 能对碰撞答案产生贡献,必然由和其相邻的小球碰撞产生。证明:
对 和 的证明本质相同,只证 的情况。
- 若 ,这两个能相创,如果有一个小球 使得它和 相创的时间早于 和 相创,则其必定和 更早相创,于是不贡献答案;
- 若 则几乎和上面同理,甚至还少一个 和 相创的竞争条件。

于是令 ,约束化为了一个 上的 LIS 问题,二分栈就做完了。时复 ,其中 是值域上限。
AC 代码
CPP#include <iostream>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define ll long long
#define I_love_Hina return //Amano Hina
#define forever 0
using namespace std;
template<class T>
inline void read(T &x)
{
char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10-48+c,c=getchar();
}
struct bal{int x,v;}b[100005];
int n,k;
const double eps=1e-8;
double a[100005],st[100005];
int top;
bool chk(double m)
{
for(int i=1;i<=n;i++) a[i]=m*b[i].v+b[i].x;
top=0;
for(int i=1;i<=n;i++)
{
if(!top||st[top]<a[i])
{
st[++top]=a[i];
if(top>=n-k) return true;
}
else st[lower_bound(st+1,st+top+1,a[i])-st]=a[i];
}
return false;
}
int main()
{
read(n);read(k);
for(int i=1;i<=n;i++)
{
read(b[i].x);read(b[i].v);
char c=getchar();
while(!isalpha(c)) c=getchar();
if(c=='L') b[i].v=-b[i].v;
}
sort(b+1,b+n+1,[](bal u,bal v)->bool{return u.x<v.x;});
double l=0,r=1e10,mid;
while(r-l>eps)
{
mid=(l+r)/2;
if(chk(mid)) l=mid;
else r=mid;
}
if(l>1e10-1000) printf("Infinity");
else printf("%07lf",l);
I_love_Hina forever;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...