bzoj[2402] 陶陶的难题II 树链剖分+线段树+二分答案+凸包
Posted lnxcj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj[2402] 陶陶的难题II 树链剖分+线段树+二分答案+凸包相关的知识,希望对你有一定的参考价值。
将y+q/x+p的值设为x
由于i,j互不干扰,所以我们可以将x,y p,q拉出来分别计算
问题转化为存在x,y,满足y-mid*x+q-mid*p>=0的情况下mid最大
不难发现答案具有单调性,于是二分答案
显然要取出一对(x,y)或(p,q)使y(q)-x(p)*mid尽可能大
以x,y举例,若取点1比取点2更优(x1>x2),则(y1-y2)/(x1-x2)>=mid
用单调栈维护上凸包,存到线段树中
查询时二分凸包
写麻烦了。。。
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,tot,tp; 7 double ans; 8 struct node{ 9 double x,y; 10 }pox[30005],poq[30005],mst; 11 vector<node>segx[30000*5+5]; 12 vector<node>segq[30000*5+5]; 13 int ch[30005]; 14 node tm1[30005],tm2[30005]; 15 int pos[30005],grand[30005]; 16 int head[30005],dep[30005]; 17 int siz[30005],son[30005]; 18 int fa[30005],stk[30005]; 19 struct Edge{ 20 int fr; 21 int to; 22 int nxt; 23 }edge[60005]; 24 bool operator == (node a,node b){ 25 return a.x-b.x<=0.0000001&&b.x-a.x<=0.0000001&&a.y-b.y<=0.0000001&&b.y-a.y<=0.0000001; 26 } 27 int cmp(node a,node b){ 28 return a.x<b.x; 29 } 30 void init(){ 31 dep[1]=1; 32 memset(head,-1,sizeof(head)); 33 } 34 void addedge(int u,int v){ 35 edge[cnt].fr=u; 36 edge[cnt].to=v; 37 edge[cnt].nxt=head[u]; 38 head[u]=cnt++; 39 } 40 void dfs1(int u){ 41 siz[u]=1; 42 for(int i=head[u];i!=-1;i=edge[i].nxt){ 43 int v=edge[i].to; 44 if(v==fa[u])continue; 45 fa[v]=u;dep[v]=dep[u]+1; 46 dfs1(v);siz[u]+=siz[v]; 47 if(siz[v]>siz[son[u]])son[u]=v; 48 } 49 } 50 void dfs2(int u){ 51 if(son[fa[u]]!=u)grand[u]=u; 52 else grand[u]=grand[fa[u]]; 53 stk[++tp]=u;pos[u]=tp; 54 if(son[u])dfs2(son[u]); 55 for(int i=head[u];i!=-1;i=edge[i].nxt){ 56 int v=edge[i].to; 57 if(v==fa[u])continue; 58 if(v!=son[u])dfs2(v); 59 } 60 } 61 int lca(int x,int y){ 62 while(grand[x]!=grand[y]){ 63 if(dep[grand[x]]<dep[grand[y]])swap(x,y); 64 x=fa[grand[x]]; 65 } 66 if(dep[x]>dep[y])swap(x,y); 67 return x; 68 } 69 void build(int u,int l,int r){ 70 for(int i=l;i<=r;i++){ 71 tm1[i]=pox[stk[i]]; 72 tm2[i]=poq[stk[i]]; 73 } 74 sort(tm1+l,tm1+r+1,cmp); 75 sort(tm2+l,tm2+r+1,cmp); 76 tp=0; 77 for(int i=l;i<=r;i++){ 78 while(tp>1&&1ll*(tm1[ch[tp]].y-tm1[ch[tp-1]].y)*(tm1[i].x-tm1[ch[tp]].x)<1ll*(tm1[i].y-tm1[ch[tp]].y)*(tm1[ch[tp]].x-tm1[ch[tp-1]].x)){ 79 tp--; 80 }ch[++tp]=i; 81 } 82 for(int i=1;i<=tp;i++)segx[u].push_back(tm1[ch[i]]); 83 tp=0; 84 for(int i=l;i<=r;i++){ 85 while(tp>1&&1ll*(tm2[ch[tp]].y-tm2[ch[tp-1]].y)*(tm2[i].x-tm2[ch[tp]].x)<1ll*(tm2[i].y-tm2[ch[tp]].y)*(tm2[ch[tp]].x-tm2[ch[tp-1]].x)){ 86 tp--; 87 }ch[++tp]=i; 88 } 89 for(int i=1;i<=tp;i++)segq[u].push_back(tm2[ch[i]]); 90 if(l==r)return; 91 int mid=(l+r)>>1; 92 build(u<<1,l,mid); 93 build(u<<1|1,mid+1,r); 94 } 95 node queryx(int u,int l,int r,int ql,int qr,double qv){ 96 if(l>=ql&&r<=qr){ 97 int le=0,ri=segx[u].size()-1; 98 while(le<=ri){ 99 int mid=(le+ri)>>1; 100 if(!mid)le=mid+1; 101 else if(1ll*(segx[u][mid].y-segx[u][mid-1].y)>1ll*(segx[u][mid].x-segx[u][mid-1].x)*qv)le=mid+1; 102 else ri=mid-1; 103 } 104 return segx[u][ri]; 105 }int mid=(l+r)>>1; 106 if(qr<=mid)return queryx(u<<1,l,mid,ql,qr,qv); 107 else if(ql>mid)return queryx(u<<1|1,mid+1,r,ql,qr,qv); 108 else{ 109 node a=queryx(u<<1,l,mid,ql,qr,qv); 110 node b=queryx(u<<1|1,mid+1,r,ql,qr,qv); 111 if(a.x<b.x)swap(a,b); 112 node ret=(1ll*(a.y-b.y)<1ll*qv*(a.x-b.x))?b:a; 113 return ret; 114 } 115 } 116 node queryq(int u,int l,int r,int ql,int qr,double qv){ 117 if(l>=ql&&r<=qr){ 118 int le=0,ri=segq[u].size()-1; 119 while(le<=ri){ 120 int mid=(le+ri)>>1; 121 if(!mid)le=mid+1; 122 else if(1ll*(segq[u][mid].y-segq[u][mid-1].y)>1ll*(segq[u][mid].x-segq[u][mid-1].x)*qv)le=mid+1; 123 else ri=mid-1; 124 } 125 return segq[u][ri]; 126 }int mid=(l+r)>>1; 127 if(qr<=mid)return queryq(u<<1,l,mid,ql,qr,qv); 128 else if(ql>mid)return queryq(u<<1|1,mid+1,r,ql,qr,qv); 129 else{ 130 node a=queryq(u<<1,l,mid,ql,qr,qv); 131 node b=queryq(u<<1|1,mid+1,r,ql,qr,qv); 132 if(a.x<b.x)swap(a,b); 133 node ret=(1ll*(a.y-b.y)<1ll*qv*(a.x-b.x))?b:a; 134 return ret; 135 } 136 } 137 int main(){ 138 init(); 139 scanf("%d",&n); 140 for(int i=1;i<=n;i++)scanf("%lf",&pox[i].x); 141 for(int i=1;i<=n;i++)scanf("%lf",&pox[i].y); 142 for(int i=1;i<=n;i++)scanf("%lf",&poq[i].x); 143 for(int i=1;i<=n;i++)scanf("%lf",&poq[i].y); 144 for(int i=1;i<n;i++){ 145 int u,v; 146 scanf("%d%d",&u,&v); 147 addedge(u,v); 148 addedge(v,u); 149 }dfs1(1);dfs2(1); 150 build(1,1,n); 151 scanf("%d",&m); 152 for(int i=1;i<=m;i++){ 153 double ans=0; 154 node ans1,ans2,tmp1,tmp2; 155 ans1=ans2=tmp1=tmp2=mst; 156 int u,v,now,f; 157 double l,r; 158 scanf("%d%d",&u,&v); 159 l=0,r=100000;f=lca(u,v); 160 while(r-l>=0.0001){ 161 double mid=(l+r)/2;now=u; 162 while(dep[grand[now]]>dep[f]){ 163 tmp1=queryx(1,1,n,pos[grand[now]],pos[now],mid); 164 tmp2=queryq(1,1,n,pos[grand[now]],pos[now],mid); 165 if(ans1==mst)ans1=tmp1; 166 if(ans2==mst)ans2=tmp2; 167 if(tmp1.x>ans1.x)swap(ans1,tmp1); 168 if(tmp2.x>ans2.x)swap(ans2,tmp2); 169 ans1=(1ll*(ans1.y-tmp1.y)<1ll*(ans1.x-tmp1.x)*mid)?tmp1:ans1; 170 ans2=(1ll*(ans2.y-tmp2.y)<1ll*(ans2.x-tmp2.x)*mid)?tmp2:ans2; 171 now=fa[grand[now]]; 172 } 173 tmp1=queryx(1,1,n,pos[f],pos[now],mid); 174 tmp2=queryq(1,1,n,pos[f],pos[now],mid); 175 if(ans1==mst)ans1=tmp1; 176 if(ans2==mst)ans2=tmp2; 177 if(tmp1.x>ans1.x)swap(ans1,tmp1); 178 if(tmp2.x>ans2.x)swap(ans2,tmp2); 179 ans1=(1ll*(ans1.y-tmp1.y)<1ll*(ans1.x-tmp1.x)*mid)?tmp1:ans1; 180 ans2=(1ll*(ans2.y-tmp2.y)<1ll*(ans2.x-tmp2.x)*mid)?tmp2:ans2; 181 now=v; 182 while(dep[grand[now]]>dep[f]){ 183 tmp1=queryx(1,1,n,pos[grand[now]],pos[now],mid); 184 tmp2=queryq(1,1,n,pos[grand[now]],pos[now],mid); 185 if(ans1==mst)ans1=tmp1; 186 if(ans2==mst)ans2=tmp2; 187 if(tmp1.x>ans1.x)swap(ans1,tmp1); 188 if(tmp2.x>ans2.x)swap(ans2,tmp2); 189 ans1=(1ll*(ans1.y-tmp1.y)<1ll*(ans1.x-tmp1.x)*mid)?tmp1:ans1; 190 ans2=(1ll*(ans2.y-tmp2.y)<1ll*(ans2.x-tmp2.x)*mid)?tmp2:ans2; 191 now=fa[grand[now]]; 192 } 193 tmp1=queryx(1,1,n,pos[f],pos[now],mid); 194 tmp2=queryq(1,1,n,pos[f],pos[now],mid); 195 if(ans1==mst)ans1=tmp1; 196 if(ans2==mst)ans2=tmp2; 197 if(tmp1.x>ans1.x)swap(ans1,tmp1); 198 if(tmp2.x>ans2.x)swap(ans2,tmp2); 199 ans1=(1ll*(ans1.y-tmp1.y)<1ll*(ans1.x-tmp1.x)*mid)?tmp1:ans1; 200 ans2=(1ll*(ans2.y-tmp2.y)<1ll*(ans2.x-tmp2.x)*mid)?tmp2:ans2; 201 if(ans1.y-ans1.x*mid+ans2.y-ans2.x*mid>0)l=mid; 202 else r=mid; 203 } 204 printf("%.4lf ",r); 205 } 206 return 0; 207 }
以上是关于bzoj[2402] 陶陶的难题II 树链剖分+线段树+二分答案+凸包的主要内容,如果未能解决你的问题,请参考以下文章
bzoj2402 陶陶的难题II 分数规划+树剖+线段树维护凸壳+二分
bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线