专栏文章

【题解】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 的转移,然而代价函数长这样:
t(i,j)=xixjvjvit(i,j)=\frac{x_i-x_j}{v_j-v_i}
这个东笔者已经替你们思考了四个半小时了,它没有单调性、限制后的 1D 问题不是凸包、不满足四边形不等式。妥妥的 O(n3)\mathcal O(n^3) 优化不了。
考虑回二分,二分能让我们得到什么?多出来一个最低代价 midmid 的限制。于是要保证选出的任意 i,ji,j 满足 xixjvjvimid\frac{x_i-x_j}{v_j-v_i}\ge mid,于是就可以分离变量了,强令 xi<xjx_i<x_j,得到 xjxi(vivj)midx_j-x_i\ge (v_i-v_j)mid,再化一下变量就分离啦:xj+vjmidxi+vimidx_j+v_j\cdot mid\ge x_i+v_i\cdot mid,但要记住我们钦定了 xi<xjx_i<x_j
在 DP 之前,还要证一个东西。
注意到如果某一小球 ii 能对碰撞答案产生贡献,必然由和其相邻的小球碰撞产生。证明:
(i,i1)(i,i-1)(i,i+1)(i,i+1) 的证明本质相同,只证 (i,i+1)(i,i+1) 的情况。
  • vi>vi+1v_i>v_{i+1},这两个能相创,如果有一个小球 jj 使得它和 ii 相创的时间早于 iii+1i+1 相创,则其必定和 i+1i+1 更早相创,于是不贡献答案;
  • vivi+1v_i\le v_{i+1} 则几乎和上面同理,甚至还少一个 iii+1i+1 相创的竞争条件。
闵可夫斯基时空图
于是令 bi=xi+vimidb_i=x_i+v_i\cdot mid,约束化为了一个 bb 上的 LIS 问题,二分栈就做完了。时复 O(nlognlogV)\mathcal O(n\log n\log V),其中 VV 是值域上限。

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 条评论,欢迎与作者交流。

正在加载评论...