传送门
题解:
把每个点的 S − T S-T S−T 的图像画出来 f i ( x ) = − i x + A i f_i(x)=-ix+A_i fi(x)=−ix+Ai。很明显要问的就是允许走交点的情况下 i i i 到达第 Q i Q_i Qi 的位置的最小横坐标是多少。
考虑 A [ Q i ] A[Q_i] A[Qi] 和 A [ i ] A[i] A[i] 的大小关系,它们决定在 x = 0 x=0 x=0 的时候那条线在上面,于是我们的策略也就决定是向上跑还是向下跑。
不难发现具体的跑法就是贪心,就是能向上就向上,能向下就向下,当目标在上方的时候,始终走自己能达到的最大的纵坐标,否则始终走自己能达到的最小的纵坐标。
这样一来,每个点的决策是唯一的,预处理一下然后倍增即可。
预处理可以瞎写一个类似半平面交的东西,从某种意义上还更像是凸包。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
char obuf[(int)(3e7+7)],*oh=obuf,ch[23];
template<typename T>void print(T a,char c){
if(a<0)a=-a,*oh++='-';int tl=0;
do ch[++tl]=a%10; while(a/=10);
while(tl)*oh++=ch[tl--]^48;*oh++=c;
}struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=2e5+7,LOG=19;
cs double eps=1e-7;
int n,A[N],id[N];
inline bool cmp_id(int i,int j){
return A[i]<A[j];
}inline double inter_x(int i,int j){
return 1.*(A[i]-A[j])/(i-j);
}
int up[LOG][N],dn[LOG][N];
void build(){
static int q[N],qn;q[qn=0]=0;
for(int re i=n;i;--i){
int p=id[i];
while((qn&&inter_x(q[qn],p)<0)||(qn>1&&inter_x(p,q[qn])>inter_x(q[qn-1],q[qn])))--qn;
dn[0][p]=q[qn];q[++qn]=p;
}q[qn=0]=0;
for(int re i=1;i<=n;++i){
int p=id[i];
while((qn&&inter_x(q[qn],p)<0)||(qn>1&&inter_x(p,q[qn])>inter_x(q[qn-1],q[qn])))--qn;
up[0][p]=q[qn];q[++qn]=p;
}
for(int re i=1;i<LOG;++i)
for(int re j=1;j<=n;++j){
up[i][j]=up[i-1][up[i-1][j]];
dn[i][j]=dn[i-1][dn[i-1][j]];
}
}
bool go_up(int u,int v){
if(!up[0][u])return false;
double x=inter_x(up[0][u],u);
double y=A[u]-u*x;
return y+eps<=A[v]-x*v;
}
bool go_dn(int u,int v){
if(!dn[0][u])return false;
double x=inter_x(dn[0][u],u);
double y=A[u]-u*x;
return y-eps>=A[v]-x*v;
}
void Main(){n=gi();
for(int re i=1;i<=n;++i)
A[i]=gi(),id[i]=i;
std::sort(id+1,id+n+1,cmp_id);build();
for(int re i=1;i<=n;++i){
int q=gi(),u=i;
if(A[u]<A[q]){
if(go_up(u,q)){
for(int re i=LOG-1;~i;--i)
if(go_up(up[i][u],q))u=up[i][u];
u=up[0][u];
if(u>q)print(-1,'\n');
else {
int x=A[q]-A[u],y=q-u;
int g=std::__gcd(x,y);
print(x/g,'/');print(y/g,'\n');
}
}else {
if(u>q)print(-1,'\n');
else {
int x=A[q]-A[u],y=q-u;
int g=std::__gcd(x,y);
print(x/g,'/');print(y/g,'\n');
}
}
}else {
if(go_dn(u,q)){
for(int re i=LOG-1;~i;--i)
if(go_dn(dn[i][u],q))u=dn[i][u];
u=dn[0][u];
if(u<q)print(-1,'\n');
else {
int x=A[u]-A[q],y=u-q;
int g=std::__gcd(x,y);
print(x/g,'/');print(y/g,'\n');
}
}else {
if(u<q)print(-1,'\n');
else {
int x=A[u]-A[q],y=u-q;
int g=std::__gcd(x,y);
print(x/g,'/');print(y/g,'\n');
}
}
}
}
}
inline void file(){
#ifdef zxyoi
freopen("falling.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("falling.in","r",stdin);
freopen("falling.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}