题解:P9314 [EGOI2021] Railway / 瑞士铁路

交了 3333 发才过,喜提新纪录。

Solution P9314

Idea

显然是可以离线做的。我们预处理出两列车相遇的地点,判断是否在隧道里即可。

然后就是已知两列车出发时间 ccdd,求两列车相遇地点的公式:

  • cdc\le ddis=dc+s(dc)2dis=d-c+\dfrac{s-(d-c)}{2}
  • c>dc>ddis=s(cd+s(cd)2)dis=s-(c-d+\dfrac{s-(c-d)}{2})

在本文章视角下,出发时间为 dd 的火车从左边出发。

下面是证明:

如果一列火车在 dd 时间从 00 点出发,相当于它从 cc 时间从 (dc)-(d-c) 点出发。

还不理解的话可以看图理解。

至于 c>dc>d,可以看作把 cdc\le d 的情况以 s2\dfrac{s}{2} 为对称轴对称了一下。

最后直接双指针检验即可。

#include<bits/stdc++.h>
#define ld long double
#define int long long
using namespace std;
const int N=1000005,M=6000005;
int l[N],r[N],n,cnt,s,t,m,a[N],b[N];
ld dis[M];
main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>s>>t>>m>>n;
	for(int i=1;i<=t;i++){
		cin>>l[i];
	}
	for(int i=1;i<=t;i++){
		cin>>r[i];
	}
	for(int i=1;i<=m;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			if(abs(a[i]-b[j])>=s)continue;
			if(a[i]<=b[j])dis[++cnt]=(ld)(b[j]-a[i])+(ld)(s-(b[j]-a[i]))/2.0;
			else dis[++cnt]=s-(ld)(a[i]-b[j])-(ld)(s-(a[i]-b[j]))/2.0;
		}
	} 
	sort(dis+1,dis+cnt+1);
	int j=1;
	for(int i=1;i<=cnt;i++){
		while(dis[i]>=(ld)r[j]&&j<t) j++;
		if(dis[i]>(ld)l[j]&&dis[i]<(ld)r[j]){
			cout<<"YES";
			return 0;
		}
	}
	cout<<"NO";
	return 0;
}
posted @   Weslie_qwq  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示