BZOJ 2402 陶陶的难题II (01分数规划+树剖+线段树+凸包+二分)

题目大意:略

一定范围内求最大值,考虑二分答案

设现在选择的答案是$mid$,$max \left \{ \frac{yi+qj}{xi+pj} \right \} \geq mid $

展开可得,$(yi-mid*xi)+(qj-mid*pj)>=0$,只要存在$i,j$使得这个式子成立,说明$mid$能作为答案

题目并没有要求我们不能选择同一个节点,所以$i,j$之间没有任何关联

现在需要求出$max \left \{ yi-mid*xi \right \}$,$q,p$和$x,y$同理

移项,$yi=mid*xi+b$,求$b$的最大值,发现这是一个一次函数的形式

线段树维护树链剖分序,线段树上每个节点都挂一个上凸包,每次用一条斜率为$mid$的直线去切这个凸包即可

总时间$O(nlog^{4}n)$,理论上过不去,但#巨佬说跑不满

  1 #include <cmath>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define N1 30010
  7 #define S1 (N1<<1)
  8 #define T1 (N1<<2)
  9 #define ll long long
 10 #define uint unsigned int
 11 #define rint register int 
 12 #define dd double
 13 #define il inline 
 14 #define inf 233333333
 15 using namespace std;
 16 
 17 const dd eps=0.000001;
 18 int gint()
 19 {
 20     int ret=0,fh=1;char c=getchar();
 21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
 23     return ret*fh;
 24 }
 25 int n,m;
 26 struct Edge{
 27 int to[S1],nxt[S1],head[N1],cte;
 28 void ae(int u,int v)
 29 {cte++,to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
 30 }E;
 31 struct node{int id;dd val;}tmp[N1];
 32 int cmp1(node s1,node s2){return s1.val<s2.val;}
 33 int stk[N1];
 34 struct SEG{
 35 vector<int>cvh[T1];
 36 void build(int l,int r,int rt,int *A,dd *X,dd *Y)
 37 {
 38     int i,j,cnt=0,tp=0,mid;
 39     for(i=l;i<=r;i++) cnt++,tmp[cnt].id=A[i],tmp[cnt].val=X[A[i]];
 40     sort(tmp+1,tmp+cnt+1,cmp1);
 41     stk[++tp]=tmp[1].id;
 42     for(i=2;i<=cnt;i++)
 43     {
 44         j=tmp[i].id;
 45         while(tp>1&&(Y[j]-Y[stk[tp-1]])*(X[stk[tp]]-X[stk[tp-1]])>=(Y[stk[tp]]-Y[stk[tp-1]])*(X[j]-X[stk[tp-1]])) tp--;
 46         stk[++tp]=j;
 47     }
 48     for(i=1;i<=tp;i++) cvh[rt].push_back(stk[i]);
 49     if(l==r) return;
 50     mid=(l+r)>>1;
 51     build(l,mid,rt<<1,A,X,Y);
 52     build(mid+1,r,rt<<1|1,A,X,Y);
 53 }
 54 dd cvh_query(int rt,dd K,dd *X,dd *Y)
 55 {
 56     if(cvh[rt].size()==1) return Y[cvh[rt][0]]-X[cvh[rt][0]]*K;
 57     int i,l=1,r=cvh[rt].size()-1,mid,p=0,a,b;
 58     a=cvh[rt][0],b=cvh[rt][1];
 59     if((Y[b]-Y[a])<=K*(X[b]-X[a])) return Y[a]-X[a]*K;
 60     while(l<=r){
 61         mid=(l+r)>>1,a=cvh[rt][mid-1],b=cvh[rt][mid];
 62         if((Y[b]-Y[a])>=K*(X[b]-X[a])) p=mid,l=mid+1;
 63         else r=mid-1;
 64     }return Y[cvh[rt][p]]-X[cvh[rt][p]]*K;
 65 }
 66 dd query(int L,int R,int l,int r,int rt,dd K,dd *X,dd *Y)
 67 {
 68     if(L<=l&&r<=R) 
 69         return cvh_query(rt,K,X,Y);
 70     int mid=(l+r)>>1; dd ans=-inf;
 71     if(L<=mid) ans=max(ans,query(L,R,l,mid,rt<<1,K,X,Y));
 72     if(R>mid) ans=max(ans,query(L,R,mid+1,r,rt<<1|1,K,X,Y));
 73     return ans;
 74 }
 75 }xy,pq;
 76 dd X[N1],Y[N1],P[N1],Q[N1];
 77 namespace cut{
 78 int fa[N1],dep[N1],sz[N1],son[N1],tp[N1];
 79 int st[N1],id[N1],tot;
 80 void dfs1(int u,int ff)
 81 {
 82     for(int j=E.head[u];j;j=E.nxt[j])
 83     {
 84         int v=E.to[j];
 85         if(v==ff) continue;
 86         dep[v]=dep[u]+1; fa[v]=u; dfs1(v,u); 
 87         sz[u]+=sz[v]; son[u]=sz[v]>sz[son[u]]?v:son[u]; 
 88     }
 89     sz[u]++;
 90 }
 91 void dfs2(int u)
 92 {
 93     st[u]=++tot,id[tot]=u;
 94     if(son[u]) tp[son[u]]=tp[u], dfs2(son[u]);
 95     for(int j=E.head[u];j;j=E.nxt[j])
 96     {
 97         int v=E.to[j];
 98         if(v==fa[u]||v==son[u]) continue;
 99         tp[v]=v; dfs2(v);
100     }
101 }
102 dd query(int x,int y,dd K)
103 {
104     dd mxy=-inf,mpq=-inf;
105     while(tp[x]!=tp[y])
106     {
107         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
108         mxy=max(mxy,xy.query(st[tp[x]],st[x],1,n,1,K,X,Y));
109         mpq=max(mpq,pq.query(st[tp[x]],st[x],1,n,1,K,P,Q));
110         x=fa[tp[x]];
111     }
112     if(dep[x]>dep[y]) swap(x,y);
113     mxy=max(mxy,xy.query(st[x],st[y],1,n,1,K,X,Y));
114     mpq=max(mpq,pq.query(st[x],st[y],1,n,1,K,P,Q));
115     return mxy+mpq;
116 }
117 void init()
118 {
119     dep[1]=1,dfs1(1,-1);
120     tp[1]=1,dfs2(1);
121     xy.build(1,n,1,id,X,Y);
122     pq.build(1,n,1,id,P,Q);
123 }
124 };
125 
126 int main()
127 {
128     scanf("%d",&n);
129     int i,x,y;
130     for(i=1;i<=n;i++) scanf("%lf",&X[i]);
131     for(i=1;i<=n;i++) scanf("%lf",&Y[i]);
132     for(i=1;i<=n;i++) scanf("%lf",&P[i]);
133     for(i=1;i<=n;i++) scanf("%lf",&Q[i]);
134     for(i=1;i<n;i++) x=gint(),y=gint(),E.ae(x,y),E.ae(y,x);
135     cut::init();
136     scanf("%d",&m);
137     dd L,R,mid,ans=0;
138     while(m--)
139     {
140         x=gint(),y=gint();
141         L=0,R=1e5;
142         while(R-L>=eps)
143         {
144             mid=(L+R)/2;
145             if(cut::query(x,y,mid)>=0) ans=mid,L=mid+eps;
146             else R=mid-eps;
147         }
148         printf("%.4lf\n",ans);
149     }
150     return 0;
151 }

 

posted @ 2018-12-20 19:02  guapisolo  阅读(198)  评论(0编辑  收藏  举报