凸包专题大概是我做的最吃shi考验代码能力的专题……

然后……大概我们的凸包可以分为静态凸包和动态凸包,从功能上可以分为决策性的凸包和计算几何性的凸包

其实没有多少区别,打就好了

静态凸包啥的我就不介绍怎么打了……

然后我推荐在弹栈的时候用叉积而不是暴力算斜率,那样讨论好多啊……

另外,一般我们不会被卡弹栈……但如果被卡时间的话,我们可以考虑二分弹栈,这样并没有什么问题……

然后我们来看看凸包可以干什么:

题目1:bzoj2402

然后我一开始想歪了……我想直接把(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 }
bzoj2402

相关文章: