版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88259273
陶陶不要给我出难题啊。。。。。。
套路分数规划+线段树+凸包二分。
sb错误不断。
AC Code:
#include<bits/stdc++.h>
#define maxn 30005
#define lc now<<1
#define rc now<<1|1
#define inf 0x3f3f3f3f
#define eps 1e-4
using namespace std;
int n;
double x[maxn],y[maxn],p[maxn],q[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
inline void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
int fa[maxn],dep[maxn],siz[maxn],son[maxn],tp[maxn],id[maxn],pos[maxn],tot,cnt_l;
void dfs1(int now,int ff)
{
dep[now] = dep[fa[now] = ff] + 1;
siz[now] = 1 , son[now] = -1;
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff)
{
dfs1(to[i],now);
siz[now] += siz[to[i]];
if(son[now] == -1 || siz[to[i]] > siz[son[now]])
son[now] = to[i];
}
}
void dfs2(int now,int ff)
{
pos[id[now] = ++tot] = now;
if(son[now]!=-1) tp[son[now]] = tp[now] , dfs2(son[now],now);
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff && to[i]!=son[now])
{
tp[to[i]] = to[i];
dfs2(to[i],now);
}
}
struct Point
{
double x,y;
Point (double x=0,double y=0):x(x),y(y){}
Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
double operator *(const Point &B)const{ return x*B.y-y*B.x; }
bool operator <(const Point &B)const{ return x == B.x ? y < B.y : x < B.x; }
}arr[maxn];
vector<Point>G[maxn<<2][2];
void build(int now,int l,int r)
{
int cnt = 0;
for(int i=l;i<=r;i++) arr[++cnt] = Point(x[pos[i]],y[pos[i]]);
sort(arr+1,arr+1+cnt);
vector<Point>&h = G[now][0];
for(int i=1,siz=0;i<=cnt;i++)
{
for(;siz>=2 && (arr[i]-h[siz-1])*(h[siz-1]-h[siz-2])<=0;siz--,h.pop_back());
h.push_back(arr[i]),siz++;//!!!
}
cnt = 0;
for(int i=l;i<=r;i++) arr[++cnt] = Point(p[pos[i]],q[pos[i]]);
sort(arr+1,arr+1+cnt);
vector<Point>&g = G[now][1];
for(int i=1,siz=0;i<=cnt;i++)
{
for(;siz>=2 && (arr[i]-g[siz-1])*(g[siz-1]-g[siz-2])<=0;siz--,g.pop_back());
g.push_back(arr[i]),siz++;
}
if(l == r) return;
int mid = (l+r) >> 1;
build(lc,l,mid),build(rc,mid+1,r);
}
bool flag = 0;
double Max[2];
void ser(vector<Point>&p,Point base,double &num)
{
if(p.size() == 0) return;
if(p.size() == 1) { num = max(num, p[0].y - p[0].x * base.y); return;}
int L = 1 , R = p.size() - 1 , mid;
for(;L<R;)
{
int mid = (L+R+1) >> 1;
if((p[mid]-p[mid-1]) * base >= 0) R = mid-1;
else L = mid;
}
if((p[L]-p[L-1]) * base >= 0) L--;
num = max( num , p[L].y - p[L].x * base.y);
}
void check(int now,double K)
{
Point base = Point(1,K);
ser(G[now][0],base,Max[0]);
ser(G[now][1],base,Max[1]);
}
void Query(int now,int l,int r,int ql,int qr,double K)
{
if(ql > r || qr < l) return;
if(ql <= l && r <= qr)
{
check(now,K);
return;
}
int mid = (l+r) >> 1;
Query(lc,l,mid,ql,qr,K),Query(rc,mid+1,r,ql,qr,K);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf",&x[i]);
for(int i=1;i<=n;i++) scanf("%lf",&y[i]);
for(int i=1;i<=n;i++) scanf("%lf",&p[i]);
for(int i=1;i<=n;i++) scanf("%lf",&q[i]);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
Node(u,v),Node(v,u);
}
dfs1(1,0),tp[1]=1,dfs2(1,0);
build(1,1,n);
int M;
scanf("%d",&M);
for(int i=0;i<M;i++)
{
int a,b,c,d;
scanf("%d%d",&a,&b),c=a,d=b;
double L = 0 , R = 1e8 , mid;
while(L<R-eps)
{
mid = (L+R) * 0.5;
Max[1] = Max[0] = -inf;
a=c,b=d;
for(;tp[a]!=tp[b];)
{
if(dep[tp[a]] > dep[tp[b]]) swap(a,b);
Query(1,1,n,id[tp[b]],id[b],mid);
b = fa[tp[b]];
}
if(dep[a] > dep[b]) swap(a,b);
Query(1,1,n,id[a],id[b],mid);
if(Max[0] + Max[1] >= 0) L = mid;
else R = mid - eps;
}
printf("%.4lf\n",L);
}
}