令左边速度为 $spd_l$,右边速度为 $spd_r$,则 $\frac{m-l}{spd_l}=\frac{r-m}{spd_r}$,即 $\frac{spd_l}{m-l}=\frac{spd_r}{r-m}$,得到 $spd_l : spd_r = m-l : r-m$,由于 $spd_l+spd_r=1$,故:
- $spd_l = \frac{m-l}{r-l},spd_r=\frac{r-m}{r-l}$
令 $s = r-l$,则 $spd_l=\frac{m-l}{s},spd_r=\frac{r-m}{s}$
对于第 $i$ 个人:
若 $x_i \le m$ $f_i(m) = y_i+\frac{x_i-l}{spd_l} = y_i+\frac{(x_i-l)s}{m-l}$
若 $x_i \gt m$ $f_i(m)=y_i+\frac{(r-x_i)s}{r-m} $
考虑令 $u = \frac{m-l}{s} \in [0,1],p_i=x_i-l,q_i=s-p_i,u_i=\frac{x_i-l}{s}$
$$ f_i(u)=\begin{cases}y_i+\frac{p_i}{u}&u_i \le u \\y_i+\frac{q_i}{1-u} & u_i \gt u\\\end{cases} $$
考虑分治 f(l,r) 表示考虑 $[l,r]$ 区间所有玩家,其中每一段区间的胜利玩家。
$l=r$返回 $([0,1],x)$
$l \lt r$返回 $merge(f(l,mid),f(mid+1,r))$
对于 merge 过程。
双指针从前到后扫描。
开始位置必然都是 $0$,结束位置必然都是 $1$。
对于最前面的两个区间,必然是一段前缀重合,此时对前缀单独提取计算答案。
然后删除双方公共前缀,剩下一段继续匹配。
考虑前缀怎么处理。
相当于问一段连续区间 $[l,r]$,$a,b$ 两个人的获胜情况。
现在找出区间 $[l,r]$ 包含哪些 $a,b$ 两人的函数交点,另外 $a,b$ 的 $u$ 值也作为切点。
按照交点将区间 $[l,r]$ 拆分为若干个子区间分别处理。
子区间取中点比较大小即可确定 $a,b$ 谁赢得子区间。
vector<pair<double,double> > cut1(l,r,a,b) 返回 $[l,r]$ 区间被 $a,b$ 的 $u$ 值切开的结果。
vector<pair<double,double> > cut2(l,r,a,b) 接受双方函数一致的区间,返回按照双方交点切开的结果。
void smalldetect(vector<SEQ>& ans,double l,double r,int a,int b) 接受双方函数一致且不存在交点的区间,将答案加入 ans。
void detectwinner(vector<SEQ>& ans,double l,double r,int a,int b) 拆分 $[l,r]$ 区间的 $a,b$ 两人胜利区间,并将区间答案加入 ans。
对于 $y_a + \frac{p_a}{x} = y_b+\frac{p_b}{x}$,可以解出 $x = \frac{p_a-p_b}{y_b-y_a}$
对于 $y_a + \frac{q_a}{1-x} = y_b+\frac{q_b}{1-x}$,可以解出 $x=1-\frac{q_a-q_b}{y_b-y_a}$
对于 $y_a + \frac{p_a}{x} = y_b+\frac{q_b}{1-x}$,令 $t=y_a-y_b$,则可以解出 $x=\frac{-t+p_a+q_b\pm\sqrt{(t-p_a-q_b)^2-4(-t)(p_a)}}{-2t}$
对于 $y_a+\frac{q_a}{1-x} = y_b+\frac{p_b}{x}$,令 $t=y_b-y_a$,则可以解出 $x = \frac{-t+p_b+q_a\pm\sqrt{(t-p_b-q_a)^2-4(-t)(p_b)}}{-2t}$
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(auto i=(a);i<=(b);i++)
#define REP(i,a,b) for(auto i=(a);i>=(b);i--)
#define FORK(i,a,b,k) for(auto i=(a);i<=(b);i+=(k))
#define REPK(i,a,b,k) for(auto i=(a);i>=(b);i-=(k))
#define pb push_back
#define mkpr make_pair
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
template<class T>
void ckmx(T& a,T b){
a=max(a,b);
}
template<class T>
void ckmn(T& a,T b){
a=min(a,b);
}
template<class T>
T gcd(T a,T b){
return !b?a:gcd(b,a%b);
}
template<class T>
T lcm(T a,T b){
return a/gcd(a,b)*b;
}
#define gc getchar()
#define eb emplace_back
#define pc putchar
#define ep empty()
#define fi first
#define se second
#define pln pc('\n');
#define islower(ch) (ch>='a'&&ch<='z')
#define isupper(ch) (ch>='A'&&ch<='Z')
#define isalpha(ch) (islower(ch)||isupper(ch))
template<class T>
void wrint(T x){
if(x<0){
x=-x;
pc('-');
}
if(x>=10){
wrint(x/10);
}
pc(x%10^48);
}
template<class T>
void wrintln(T x){
wrint(x);
pln
}
template<class T>
void read(T& x){
x=0;
int f=1;
char ch=gc;
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=gc;
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
x*=f;
}
void ioopti(){
ios::sync_with_stdio(0);
cin.tie(0);
}
void io(){
freopen("anticipate.in","r",stdin);
freopen("anticipate.out","w",stdout);
}
const double eps=1e-12;
bool chkeq(double& a,double& b){
return abs(a-b)<=eps;
}
const int maxn=2e5+5;
int n;
double l,r,x[maxn],y[maxn];
double p[maxn],q[maxn],u[maxn],s;
struct SEQ{
double l,r;
int winid;
SEQ(double l,double r,int winid):l(l),r(r),winid(winid){}
};
vector<pair<double,double> > cut1(double l,double r,int a,int b){
vector<double> cuts;
if(u[a]>=l&&u[a]<=r)cuts.eb(u[a]);
if(u[b]>=l&&u[b]<=r)cuts.eb(u[b]);
if(cuts.empty())return {mkpr(l,r)};
sort(cuts.begin(),cuts.end());
cuts.erase(unique(cuts.begin(),cuts.end()),cuts.end());
vector<pair<double,double> > res;
res.eb(mkpr(l,cuts[0]));
FOR(i,1,cuts.size()-1)res.eb(mkpr(cuts[i-1],cuts[i]));
res.eb(mkpr(cuts.back(),r));
return res;
}
double sqr(double x){
return x*x;
}
vector<pair<double,double> > cut2(double l,double r,int a,int b){
double mid=(l+r)/2;
bool a_lef=(mid>=u[a]);
bool b_lef=(mid>=u[b]);
vector<double> cuts;
if(a_lef&&b_lef){
if(!chkeq(y[a],y[b])){
double x=(p[a]-p[b])/(y[b]-y[a]);
if(x>=l&&x<=r){
cuts.eb(x);
}
}
}else if(a_lef&&!b_lef){
// a 左边,但是 b 右边
if(chkeq(y[a],y[b])){
double x=p[a]/(p[a]+q[b]);
if(x>=l&&x<=r)cuts.eb(x);
}else{
double t=y[a]-y[b];
if(sqr(t-p[a]-q[b])-4*(-t)*p[a]>=0){
double x1=(-t+p[a]+q[b]+sqrt(sqr(t-p[a]-q[b])-4*(-t)*p[a]))/(-2*t);
double x2=(-t+p[a]+q[b]-sqrt(sqr(t-p[a]-q[b])-4*(-t)*p[a]))/(-2*t);
if(x1>=l&&x1<=r)cuts.eb(x1);
if(x2>=l&&x2<=r)cuts.eb(x2);
}
}
}else if(!a_lef&&b_lef){
if(chkeq(y[a],y[b])){
double x=p[b]/(p[b]+q[a]);
if(x>=l&&x<=r)cuts.eb(x);
}else{
double t=y[b]-y[a];
if(sqr(t-p[b]-q[a])-4*(-t)*p[b]>=0){
double x1=(-t+p[b]+q[a]+sqrt(sqr(t-p[b]-q[a])-4*(-t)*p[b]))/(-2*t);
double x2=(-t+p[b]+q[a]-sqrt(sqr(t-p[b]-q[a])-4*(-t)*p[b]))/(-2*t);
if(x1>=l&&x1<=r)cuts.eb(x1);
if(x2>=l&&x2<=r)cuts.eb(x2);
}
}
}else{
if(!chkeq(y[a],y[b])){
double x=1-(q[a]-q[b])/(y[b]-y[a]);
if(x>=l&&x<=r){
cuts.eb(x);
}
}
}
sort(cuts.begin(),cuts.end());
cuts.erase(unique(cuts.begin(),cuts.end()),cuts.end());
vector<pair<double,double> > res;
if(cuts.empty()){
res.eb(l,r);
}else{
res.eb(mkpr(l,cuts[0]));
FOR(i,1,cuts.size()-1)res.eb(mkpr(cuts[i-1],cuts[i]));
res.eb(mkpr(cuts.back(),r));
}
return res;
}
double getval(int id,double m){
if(m>=u[id]){
return y[id]+p[id]/m;
}else{
return y[id]+q[id]/(1-m);
}
}
void smalldetect(vector<SEQ>& ans,double l,double r,int a,int b){
double mid=(l+r)/2;
if(getval(a,mid)>getval(b,mid))ans.eb(SEQ{l,r,a});
else ans.eb(SEQ{l,r,b});
}
void detectwinner(vector<SEQ>& ans,double l,double r,int a,int b){
auto fircuts=cut1(l,r,a,b);
for(auto [l1,r1]:fircuts){
auto seccuts=cut2(l1,r1,a,b);
for(auto [l2,r2]:seccuts){
smalldetect(ans,l2,r2,a,b);
}
}
}
vector<SEQ> merge(vector<SEQ> a,vector<SEQ> b){
vector<SEQ> res;
int i=0,j=0;
while(i<a.size()&&j<b.size()){
double mn=min(a[i].r,b[j].r);
detectwinner(res,a[i].l,mn,a[i].winid,b[j].winid);
a[i].l=mn,b[j].l=mn;
if(chkeq(a[i].l,a[i].r))i++;
if(chkeq(b[j].l,b[j].r))j++;
}
vector<SEQ> tmp;
for(auto [l,r,winid]:res){
if(!tmp.empty()&&winid==tmp.back().winid){
tmp.back().r=r;
}else{
tmp.eb(SEQ{l,r,winid});
}
}
// assert(i==a.size()&&j==b.size())
return tmp;
}
vector<SEQ> f(int l,int r){
if(l==r){
return {SEQ(0.0,1.0,l)};
}
int mid=(l+r>>1);
return merge(f(l,mid),f(mid+1,r));
}
double ans[maxn];
void solve(int id_of_test){
{
scanf("%d%lf%lf",&n,&l,&r);
FOR(i,1,n){
scanf("%lf",&x[i]);
}
FOR(i,1,n){
scanf("%lf",&y[i]);
}
}
{
s=r-l;
FOR(i,1,n){
p[i]=x[i]-l;
q[i]=s-p[i];
u[i]=(x[i]-l)/s;
}
}
auto res=f(1,n);
for(auto [l,r,winid]:res){
ans[winid]+=r-l;
}
FOR(i,1,n){
printf("%.12lf\n",ans[i]);
}
}
int main()
{
// io();
// int num;
// read(num);
int T;
T=1;
FOR(_,1,T){
solve(_);
}
return 0;
}
/*
1. 对题意的理解能否和样例对的上?
2. 每一步操作,能否和自己的想法对应上?
3. 每一步操作的正确性是否有保证?
4. 是否考虑到了所有的 case?特别是极限数据。
5. 变量的数据类型是否与其值域匹配?
6. 时间复杂度有保证吗?
7. 空间多少 MB?
*/