Description
Input
第一行包含一个正整数N,表示树中结点的个数。
第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5)。
第三行包含N个正实数,第i个数表示yi (1<=yi<=10^5)。
第四行包含N个正实数,第i个数表示pi (1<=pi<=10^5)。
第五行包含N个正实数,第i个数表示qi (1<=qi<=10^5)。
下面有N-1行,每行包含两个正整数a,b(1<=a,b<=N),表示树中的边。
第N+5行包含一个正整数M,表示询问的个数。
最后M行,每行包含正整数a,b(1<=a,b<=N),表示一次询问。
Output
共M行,每行一个实数,第i行的数表示第i次询问的答案。
只要你的输出和我们的输出相差不超过0.001即为正确。
Sample Input
5
3.0 1.0 2.0 5.0 4.0
5.0 2.0 4.0 3.0 1.0
1.0 3.0 2.0 4.0 5.0
3.0 4.0 2.0 1.0 4.0
1 2
1 3
2 4
2 5
4
2 3
4 5
2 4
3 5
3.0 1.0 2.0 5.0 4.0
5.0 2.0 4.0 3.0 1.0
1.0 3.0 2.0 4.0 5.0
3.0 4.0 2.0 1.0 4.0
1 2
1 3
2 4
2 5
4
2 3
4 5
2 4
3 5
Sample Output
2.5000
1.5000
1.5000
2.5000
1.5000
1.5000
2.5000
解题思路:
那个式子非常像0/1分数规划。
发现pq式子和xy的式子结构相同,所以用同一种方法维护。
二分答案,看表达式的值。
为了寻找最大值可以将x与y移至方程两侧,发现就是一个直线方程寻找最大截距。
凸包没跑了。
将树链上的点维护成凸包二分答案取值。
开两颗线段树存。
代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lll spc<<1 6 #define rrr spc<<1|1 7 typedef long long lnt; 8 const double eps=1e-9; 9 const int N=300000; 10 struct trnt{ 11 int l,r; 12 }; 13 struct data{ 14 double x,y; 15 bool friend operator < (data a,data b) 16 { 17 return a.x<b.x; 18 } 19 }tmp[N]; 20 struct pnt{ 21 int hd; 22 int fa; 23 int dp; 24 int tp; 25 int wgt; 26 int ind; 27 int mxs; 28 double x,y,p,q; 29 }p[N]; 30 struct ent{ 31 int twd; 32 int lst; 33 }e[N<<1]; 34 class segment_tree{ 35 public: 36 void Build(int l,int r,int spc) 37 { 38 int bot=tr[spc].l=top+1; 39 for(int i=l;i<=r;i++) 40 val[++top]=ln[i]; 41 std::sort(val+tr[spc].l,val+top+1); 42 int cel=top; 43 top=bot; 44 for(int i=bot+1;i<=cel;i++) 45 { 46 while(top>bot&&(val[top].y-val[top-1].y)*(val[i].x-val[top].x)<(val[i].y-val[top].y)*(val[top].x-val[top-1].x)-eps) 47 top--; 48 val[++top]=val[i]; 49 } 50 tr[spc].r=top; 51 if(l==r) 52 return ; 53 int mid=(l+r)>>1; 54 Build(l,mid,lll); 55 Build(mid+1,r,rrr); 56 return ; 57 } 58 double query(int l,int r,int ll,int rr,int spc,double k) 59 { 60 if(l>rr||ll>r) 61 return -1e9; 62 if(ll<=l&&r<=rr) 63 { 64 double ans; 65 int L=tr[spc].l; 66 int R=tr[spc].r; 67 while(L<R) 68 { 69 int mid=(L+R)>>1; 70 if(val[mid+1].y-val[mid].y<(val[mid+1].x-val[mid].x)*k+eps) 71 { 72 R=mid; 73 }else 74 L=mid+1; 75 } 76 ans=val[R].y-val[R].x*k; 77 return ans; 78 } 79 int mid=(l+r)>>1; 80 return std::max(query(l,mid,ll,rr,lll,k),query(mid+1,r,ll,rr,rrr,k)); 81 } 82 void Insert(int l,int r,data *a) 83 { 84 for(int i=l;i<=r;i++) 85 ln[i]=a[i]; 86 return ; 87 } 88 private: 89 trnt tr[N]; 90 data ln[N]; 91 data val[N]; 92 int top; 93 }S[2]; 94 int n,m; 95 int cnt; 96 int dfn; 97 void ade(int f,int t) 98 { 99 cnt++; 100 e[cnt].twd=t; 101 e[cnt].lst=p[f].hd; 102 p[f].hd=cnt; 103 return ; 104 } 105 void Basic_dfs(int x,int f) 106 { 107 p[x].fa=f; 108 p[x].dp=p[f].dp+1; 109 p[x].wgt=1; 110 int maxs=-1; 111 for(int i=p[x].hd;i;i=e[i].lst) 112 { 113 int to=e[i].twd; 114 if(to==f) 115 continue; 116 Basic_dfs(to,x); 117 p[x].wgt+=p[to].wgt; 118 if(maxs<p[to].wgt) 119 { 120 maxs=p[to].wgt; 121 p[x].mxs=to; 122 } 123 } 124 return ; 125 } 126 void Build_dfs(int x,int top) 127 { 128 if(!x) 129 return ; 130 p[x].ind=++dfn; 131 p[x].tp=top; 132 Build_dfs(p[x].mxs,top); 133 for(int i=p[x].hd;i;i=e[i].lst) 134 { 135 int to=e[i].twd; 136 if(p[to].ind) 137 continue; 138 Build_dfs(to,to); 139 } 140 return ; 141 } 142 int Lca(int x,int y) 143 { 144 while(p[x].tp!=p[y].tp) 145 { 146 if(p[p[x].tp].dp<p[p[y].tp].dp) 147 std::swap(x,y); 148 x=p[p[x].tp].fa; 149 } 150 if(p[x].dp>p[y].dp) 151 std::swap(x,y); 152 return x; 153 } 154 bool check(int x,int y,double lambda) 155 { 156 double a=-1e9,b=-1e9; 157 int z=Lca(x,y); 158 while(p[x].tp!=p[z].tp) 159 { 160 a=std::max(S[0].query(1,n,p[p[x].tp].ind,p[x].ind,1,lambda),a); 161 b=std::max(S[1].query(1,n,p[p[x].tp].ind,p[x].ind,1,lambda),b); 162 x=p[p[x].tp].fa; 163 } 164 a=std::max(S[0].query(1,n,p[z].ind,p[x].ind,1,lambda),a); 165 b=std::max(S[1].query(1,n,p[z].ind,p[x].ind,1,lambda),b); 166 while(p[y].tp!=p[z].tp) 167 { 168 a=std::max(S[0].query(1,n,p[p[y].tp].ind,p[y].ind,1,lambda),a); 169 b=std::max(S[1].query(1,n,p[p[y].tp].ind,p[y].ind,1,lambda),b); 170 y=p[p[y].tp].fa; 171 } 172 a=std::max(S[0].query(1,n,p[z].ind,p[y].ind,1,lambda),a); 173 b=std::max(S[1].query(1,n,p[z].ind,p[y].ind,1,lambda),b); 174 return a+b>eps; 175 } 176 int main() 177 { 178 scanf("%d",&n); 179 for(int i=1;i<=n;i++) 180 scanf("%lf",&p[i].x); 181 for(int i=1;i<=n;i++) 182 scanf("%lf",&p[i].y); 183 for(int i=1;i<=n;i++) 184 scanf("%lf",&p[i].p); 185 for(int i=1;i<=n;i++) 186 scanf("%lf",&p[i].q); 187 for(int i=1;i<n;i++) 188 { 189 int a,b; 190 scanf("%d%d",&a,&b); 191 ade(a,b); 192 ade(b,a); 193 } 194 Basic_dfs(1,1); 195 Build_dfs(1,1); 196 for(int i=1;i<=n;i++) 197 tmp[p[i].ind]=(data){p[i].x,p[i].y}; 198 S[0].Insert(1,n,tmp); 199 for(int i=1;i<=n;i++) 200 tmp[p[i].ind]=(data){p[i].p,p[i].q}; 201 S[1].Insert(1,n,tmp); 202 S[0].Build(1,n,1); 203 S[1].Build(1,n,1); 204 scanf("%d",&m); 205 while(m--) 206 { 207 int a,b; 208 scanf("%d%d",&a,&b); 209 double l=0,r=1e8; 210 while(fabs(l-r)>=1e-5) 211 { 212 double mid=(l+r)/2.00; 213 if(check(a,b,mid)) 214 l=mid; 215 else 216 r=mid; 217 } 218 printf("%.4lf ",l); 219 } 220 return 0; 221 }