凸包专题大概是我做的最吃shi考验代码能力的专题……
然后……大概我们的凸包可以分为静态凸包和动态凸包,从功能上可以分为决策性的凸包和计算几何性的凸包
其实没有多少区别,打就好了
静态凸包啥的我就不介绍怎么打了……
然后我推荐在弹栈的时候用叉积而不是暴力算斜率,那样讨论好多啊……
另外,一般我们不会被卡弹栈……但如果被卡时间的话,我们可以考虑二分弹栈,这样并没有什么问题……
然后我们来看看凸包可以干什么:
然后我一开始想歪了……我想直接把(x,y)和(p,q)当作点的坐标然后去凸壳查找
但是这样的决策点是无法定义最优的……在不同的询问点中最优是不同的……很是尴尬
然后我这么弱当然%了题解啊……
所以我们可以考虑01分数规划,二分答案k,把原来的式子变形得到
$ y_{i}-k*x_{i}+q_{i}-k*p_{i}>=0 $
然后询问的时候,我们这就是维护一个上凸壳拿一条直线卡一下
可以联系一下高中线性规划的知识
然后我们可以用熟练剖分来解决这个问题,对于链上log次询问我们取最优的最优点即可
这样的复杂度……是$mlog^{4}n$的,但是由于没啥常数,并且数据范围还很小,所以说可以过30000的全部数据
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 30010 6 #define db double 7 int e,adj[N],n; 8 db x[N],y[N],p[N],q[N]; 9 struct edge{int zhong,next;}s[N<<1]; 10 inline void add(int qi,int zhong) 11 {s[++e].zhong=zhong;s[e].next=adj[qi];adj[qi]=e;} 12 int deep[N],son[N],size[N],fa[N],dfn[N],num,top[N],anti[N]; 13 inline void dfs1(int rt,int Vater) 14 { 15 fa[rt]=Vater;deep[rt]=deep[Vater]+1,size[rt]=1; 16 register int i,u; 17 for(i=adj[rt];i;i=s[i].next) 18 if((u=s[i].zhong)!=Vater) 19 { 20 dfs1(u,rt),size[rt]+=size[u]; 21 if(size[u]>size[son[rt]])son[rt]=u; 22 } 23 } 24 inline void dfs2(int rt,int tp) 25 { 26 dfn[rt]=++num,top[rt]=tp;anti[num]=rt; 27 if(son[rt])dfs2(son[rt],tp); 28 register int i,u; 29 for(i=adj[rt];i;i=s[i].next) 30 if((u=s[i].zhong)!=fa[rt]&&u!=son[rt])dfs2(u,u); 31 } 32 struct pt 33 { 34 db x,y;pt(db a=0,db b=0){x=a,y=b;} 35 inline pt operator + (const pt &b) const {return pt(x+b.x,y+b.y);} 36 inline pt operator - (const pt &b) const {return pt(x-b.x,y-b.y);} 37 inline db operator * (const pt &b) const {return x*b.y-y*b.x;} 38 }Mem1[N<<4],*head1=Mem1,Mem2[N<<4],*head2=Mem2,sta[N]; 39 struct node 40 { 41 node *ch[2]; 42 pt *xy,*pq; 43 int lxy,lpq; 44 }*root,mem[N<<1];int tot; 45 inline bool mt1(const pt &a,const pt &b){return a.x==b.x?a.y<b.y:a.x<b.x;} 46 #define inf 0x7fffffff 47 inline double max(db a,db b){return a>b?a:b;} 48 inline int solve(pt *x,int len) 49 { 50 sort(x,x+len,mt1); 51 register int i,top=-1; 52 for(i=0;i<len;++i) 53 { 54 while(top>0&&(sta[top]-sta[top-1])*(x[i]-sta[top])>=0)--top; 55 sta[++top]=x[i]; 56 } 57 for(i=0;i<=top;++i)x[i]=sta[i]; 58 return top; 59 } 60 inline db query(pt *x,db k,int len) 61 { 62 if(len==0)return x[0].y-k*x[0].x; 63 int l=0,r=len-1,mi,ans=0; 64 pt q=pt(1,k),tmp; 65 while(l<=r) 66 { 67 mi=(l+r)>>1,tmp=x[mi+1]-x[mi]; 68 if(tmp*q>=0)ans=mi,r=mi-1; 69 else l=mi+1; 70 } 71 return max(x[ans].y-k*x[ans].x,x[ans+1].y-k*x[ans+1].x); 72 } 73 inline node* build(int l,int r) 74 { 75 node *o=mem+(tot++); 76 o->xy=head1,o->pq=head2; 77 head1+=r-l+1,head2+=r-l+1; 78 for(int i=l;i<=r;++i) 79 o->xy[i-l]=pt(x[anti[i]],y[anti[i]]),o->pq[i-l]=pt(p[anti[i]],q[anti[i]]); 80 o->lxy=solve(o->xy,r-l+1),o->lpq=solve(o->pq,r-l+1); 81 if(l==r)return o; 82 register int mi=(l+r)>>1; 83 o->ch[0]=build(l,mi),o->ch[1]=build(mi+1,r); 84 return o; 85 } 86 inline double qxy(node *o,int l,int r,int L,int R,db k) 87 { 88 if(L<=l&&r<=R)return query(o->xy,k,o->lxy); 89 register int mi=(l+r)>>1; 90 db ret=-inf; 91 if(L<=mi)ret=qxy(o->ch[0],l,mi,L,R,k); 92 if(mi<R)ret=max(ret,qxy(o->ch[1],mi+1,r,L,R,k)); 93 return ret; 94 } 95 inline double qpq(node *o,int l,int r,int L,int R,db k) 96 { 97 if(L<=l&&r<=R)return query(o->pq,k,o->lpq); 98 register int mi=(l+r)>>1; 99 db ret=-inf; 100 if(L<=mi)ret=qpq(o->ch[0],l,mi,L,R,k); 101 if(mi<R)ret=max(ret,qpq(o->ch[1],mi+1,r,L,R,k)); 102 return ret; 103 } 104 #define eps 1e-5 105 inline db queryxy(int a,int b,db k) 106 { 107 db ret=-inf; 108 while(top[a]^top[b]) 109 { 110 if(deep[top[a]]<deep[top[b]])a^=b,b^=a,a^=b; 111 ret=max(ret,qxy(root,1,n,dfn[top[a]],dfn[a],k)),a=fa[top[a]]; 112 } 113 if(deep[a]<deep[b])a^=b,b^=a,a^=b; 114 return max(ret,qxy(root,1,n,dfn[b],dfn[a],k)); 115 } 116 inline db querypq(int a,int b,db k) 117 { 118 db ret=-inf; 119 while(top[a]^top[b]) 120 { 121 if(deep[top[a]]<deep[top[b]])a^=b,b^=a,a^=b; 122 ret=max(ret,qpq(root,1,n,dfn[top[a]],dfn[a],k)),a=fa[top[a]]; 123 } 124 if(deep[a]<deep[b])a^=b,b^=a,a^=b; 125 return max(ret,qpq(root,1,n,dfn[b],dfn[a],k)); 126 } 127 int main() 128 { 129 // freopen("Ark.in","r",stdin); 130 register int i,m,a,b;scanf("%d",&n); 131 for(i=1;i<=n;++i)scanf("%lf",&x[i]); 132 for(i=1;i<=n;++i)scanf("%lf",&y[i]); 133 for(i=1;i<=n;++i)scanf("%lf",&p[i]); 134 for(i=1;i<=n;++i)scanf("%lf",&q[i]); 135 for(i=1;i<n;++i)scanf("%d%d",&a,&b),add(a,b),add(b,a); 136 dfs1(1,0),dfs2(1,1),root=build(1,n); 137 db l,r,mi,ans;scanf("%d",&m); 138 while(m--) 139 { 140 scanf("%d%d",&a,&b); 141 l=0,r=1e5,ans=0; 142 while(r-l>eps) 143 { 144 mi=(l+r)/2; 145 if(queryxy(a,b,mi)+querypq(a,b,mi)>=0)l=mi,ans=mi; 146 else r=mi; 147 } 148 printf("%.4lf\n",ans); 149 } 150 }