Description
一个周长为
L
的圆弧上面有
Input
第一行一整数
T
表示用例组数,每组用例首先输入两个整数
(T≤20,1≤L≤106,0≤di<L,|vi|≤106,0≤wi<n,∑n≤105)
Output
对于每组用例,输出最后一个点被标记的时刻的最简分数形式
Sample Input
1
8 8
2 1 5 7 4 6 0 3
86 27 -85 -8 11 73 -37 -69
0 6 4 4 3 0 2 5
Sample Output
4/61
Solution
对于一个时间
t
,假设
二分
t
,对于一个
对于区间
[l,r]
,假设已经解决
[l,mid]
和
[mid+1,r]
,那么合并过程中需要知道两个区间的互相影响,在归并过程中,维护左区间
val
的最值
tlmin,tlmax
和右区间
val
的最值
trmin,trmax
以及左右区间能量值小于当前插入点能量值的点的最值
lmin,lmax,rmin,rmax
,每次比较两个区间前端元素
i
和
对于一个时间 t ,如果分治结束后,存在一个点未被标记且其能量值不是最大值,由于任意两点速度不同,那么这个点之后还可以被标记,说明该二分值过小,否则说明二分值满足条件,还可以寻找更小的答案
由于答案要输出分数形式,考虑最后一个被标记的点
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define maxn 100005
#define INF 1e20
#define eps 1e-6
struct node
{
int d,v,w,id;
double val;
bool operator<(const node &b)const
{
return d<b.d;
}
}p[maxn],a[maxn],temp[maxn];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int T,n,L,Maxw,last,vis[maxn];
void CDQ(int l,int r)
{
if(l>=r)return ;
int mid=(l+r)/2;
CDQ(l,mid),CDQ(mid+1,r);
int i=l,j=mid+1,k=l;
double tlmin=INF,tlmax=-INF,trmin=INF,trmax=-INF;
double lmin=INF,lmax=-INF,rmin=INF,rmax=-INF;
while(i<=mid|| j<=r)
{
if(j==r+1||i<=mid&&a[i].w>a[j].w)
{
if(k>l&&temp[k-1].w!=a[i].w)
lmin=tlmin,lmax=tlmax,rmin=trmin,rmax=trmax;
if(a[i].val>=rmin||a[i].val<=rmax-L)vis[a[i].id]=1;
tlmin=min(tlmin,a[i].val),tlmax=max(tlmax,a[i].val);
temp[k++]=a[i++];
}
else
{
if(k>l&&temp[k-1].w!=a[j].w)
lmin=tlmin,lmax=tlmax,rmin=trmin,rmax=trmax;
if(a[j].val<=lmax||a[j].val>=lmin+L)vis[a[j].id]=1;
trmin=min(trmin,a[j].val),trmax=max(trmax,a[j].val);
temp[k++]=a[j++];
}
}
for(int i=l;i<=r;i++)a[i]=temp[i];
}
bool check(double t)
{
for(int i=1;i<=n;i++)a[i]=p[i],a[i].val=a[i].d+t*a[i].v,vis[i]=0;
CDQ(1,n);
for(int i=1;i<=n;i++)
if(!vis[i]&&p[i].w!=Maxw)
{
last=i;
return 0;
}
return 1;
}
void update(node a,node b,int &x,int &y)
{
if(a.v<b.v)swap(a,b);
int tx,ty=a.v-b.v;
if(a.d<b.d)tx=b.d-a.d;
else tx=L+b.d-a.d;
if(1ll*tx*y<=1ll*x*ty)x=tx,y=ty;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&L);
for(int i=1;i<=n;i++)scanf("%d",&p[i].d);
for(int i=1;i<=n;i++)scanf("%d",&p[i].v);
for(int i=1;i<=n;i++)scanf("%d",&p[i].w);
sort(p+1,p+n+1);
Maxw=p[1].w;
for(int i=2;i<=n;i++)Maxw=max(Maxw,p[i].w);
for(int i=1;i<=n;i++)p[i].id=i;
double l=0,r=L,mid;
last=0;
while(l<r-eps)
{
mid=0.5*(l+r);
if(check(mid))r=mid;
else l=mid;
}
if(!last)printf("0\n");
else
{
int x=0,y=0;
for(int i=1;i<=n;i++)
if(p[i].w>p[last].w)update(p[i],p[last],x,y);
int g=gcd(x,y);
printf("%d/%d\n",x/g,y/g);
}
}
return 0;
}