1 条题解
-
0
#include<bits/stdc++.h> using namespace std; const double pi=3.14159265358979323846; int nex[6005],beg[6005],to[6005],r[3005],n,m,t,e,s,ee[3005]; struct T{ double x,y,sonf[15],faf,wtcl; int d,fa[25],sn,snn,son[15]; }tree[3005];//定义节点,sonf、faf为儿子节点(圆)、父亲节点(圆)的幅角 void add(int x,int y){ to[++e]=y; nex[e]=beg[x]; beg[x]=e; }//链式前向星 double dist(int d,double x,double y){ if(x>y)return (2*pi-x+y)*r[d]; return (y-x)*r[d]; }//计算两点在尺寸为d的圆上逆时针距离 void dfs(int s){ for(int i=1;(1<<i)<=tree[s].d;i++) tree[s].fa[i]=tree[tree[s].fa[i-1]].fa[i-1]; for(int i=beg[s];i;i=nex[i])dfs(to[i]); }//倍增预处理 void dfs2(int s){ for(int i=1;i<=tree[s].sn;i++) if(tree[s].d%2==0){ tree[tree[s].son[i]].wtcl=tree[s].wtcl+dist(tree[s].d,tree[s].sonf[i],tree[s].faf); dfs2(tree[s].son[i]); } else { tree[tree[s].son[i]].wtcl=tree[s].wtcl+dist(tree[s].d,tree[s].faf,tree[s].sonf[i]); dfs2(tree[s].son[i]); } }//标准方向的距离预处理 int lca(int a,int b){ if(tree[a].d>tree[b].d) swap(a,b); for(int i=20;i>=0;i--) if(tree[a].d+(1<<i)<=tree[b].d) b=tree[b].fa[i]; if(a==b)return -1; for(int i=20;i>=0;i--) if(tree[a].fa[i]!=tree[b].fa[i]){ a=tree[a].fa[i]; b=tree[b].fa[i]; } return tree[a].fa[0]; }//LCA int main(){ scanf("%d%d%d",&n,&m,&t); r[0]=1e5; ee[0]=1e5;//ee是r的前缀和 for(int i=1;i<=n;i++) scanf("%d",&r[i]),ee[i]=ee[i-1]+r[i]; s=1;//根节点为1 for(int i=1;i<=m;i++){ scanf("%lf%lf%d%d",&tree[i].x,&tree[i].y,&tree[i].d,&tree[i].fa[0]);//其实尺寸就相当于深度 tree[tree[i].fa[0]].son[++tree[tree[i].fa[0]].sn]=i;//记录儿子 add(tree[i].fa[0],i);//加边 } for(int i=2;i<=m;i++){ tree[tree[i].fa[0]].snn++; if(tree[i].x==tree[tree[i].fa[0]].x){ if(tree[i].y>tree[tree[i].fa[0]].y)tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=pi/2; else tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=3*pi/2; } else{ if(tree[i].x>tree[tree[i].fa[0]].x&&tree[i].y>=tree[tree[i].fa[0]].y)tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=atan((tree[i].y-tree[tree[i].fa[0]].y)/(tree[i].x-tree[tree[i].fa[0]].x)); if(tree[i].x<tree[tree[i].fa[0]].x&&tree[i].y>=tree[tree[i].fa[0]].y)tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=pi+atan((tree[i].y-tree[tree[i].fa[0]].y)/(tree[i].x-tree[tree[i].fa[0]].x)); if(tree[i].x<tree[tree[i].fa[0]].x&&tree[i].y<tree[tree[i].fa[0]].y)tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=pi+atan((tree[i].y-tree[tree[i].fa[0]].y)/(tree[i].x-tree[tree[i].fa[0]].x)); if(tree[i].x>tree[tree[i].fa[0]].x&&tree[i].y<tree[tree[i].fa[0]].y)tree[tree[i].fa[0]].sonf[tree[tree[i].fa[0]].snn]=2*pi+atan((tree[i].y-tree[tree[i].fa[0]].y)/(tree[i].x-tree[tree[i].fa[0]].x)); }//分四个区域和平行于x轴的两种情况讨论幅角 }//求出sonf for(int i=1;i<=m;i++) for(int j=1;j<=tree[i].sn;j++){ if(tree[i].x==tree[tree[i].son[j]].x){ if(tree[i].y>tree[tree[i].son[j]].y)tree[tree[i].son[j]].faf=pi/2; else tree[tree[i].son[j]].faf=3*pi/2; } else{ if(tree[i].x>tree[tree[i].son[j]].x&&tree[i].y>=tree[tree[i].son[j]].y)tree[tree[i].son[j]].faf=atan((tree[i].y-tree[tree[i].son[j]].y)/(tree[i].x-tree[tree[i].son[j]].x)); if(tree[i].x<tree[tree[i].son[j]].x&&tree[i].y>=tree[tree[i].son[j]].y)tree[tree[i].son[j]].faf=pi+atan((tree[i].y-tree[tree[i].son[j]].y)/(tree[i].x-tree[tree[i].son[j]].x)); if(tree[i].x<tree[tree[i].son[j]].x&&tree[i].y<tree[tree[i].son[j]].y)tree[tree[i].son[j]].faf=pi+atan((tree[i].y-tree[tree[i].son[j]].y)/(tree[i].x-tree[tree[i].son[j]].x)); if(tree[i].x>tree[tree[i].son[j]].x&&tree[i].y<tree[tree[i].son[j]].y)tree[tree[i].son[j]].faf=2*pi+atan((tree[i].y-tree[tree[i].son[j]].y)/(tree[i].x-tree[tree[i].son[j]].x)); }//分四个区域和平行于x轴的两种情况讨论幅角 }//求出faf dfs(s);//倍增 for(int i=1;i<=tree[1].sn;i++) dfs2(tree[1].son[i]);//求出标准方向上的距离 while(t--){ int x,y,xxx,yyy; double ans,xx,yy,xf,yf,xh,yh,xxxx,yyyy,hh; scanf("%d%lf%d%lf",&x,&xf,&y,&yf); if(x==y){ printf("%.0lf\n",min(fabs(xf-yf),2*pi-fabs(xf-yf))*r[tree[x].d]/pi); continue; }//在同一圆上的情况 int h=lca(x,y);//求LCA if(h==-1){ ans=0; if(tree[x].d>tree[y].d) swap(x,y),swap(xf,yf); int kk; for(int i=1;i<=tree[x].sn;i++) if(lca(tree[x].son[i],y)==-1)kk=i; if(tree[x].d%2==0)ans+=dist(tree[x].d,tree[x].sonf[kk],xf); else ans+=dist(tree[x].d,xf,tree[x].sonf[kk]); if(tree[y].d%2==0)ans+=dist(tree[y].d,yf,tree[y].faf); else ans+=dist(tree[y].d,tree[y].faf,yf); ans+=tree[y].wtcl; ans-=tree[tree[x].son[kk]].wtcl; if(ans>pi*(ee[tree[y].d]-ee[tree[x].d]+r[tree[x].d]))ans=2*pi*(ee[tree[y].d]-ee[tree[x].d]+r[tree[x].d])-ans; printf("%.0lf\n",ans/pi); continue; }//“直系血亲”的情况 for(int i=1;i<=tree[h].sn;i++){ if(lca(tree[h].son[i],x)==-1)xxx=tree[h].son[i],xxxx=tree[h].sonf[i]; if(lca(tree[h].son[i],y)==-1)yyy=tree[h].son[i],yyyy=tree[h].sonf[i]; } if(tree[x].d%2==0)xx=dist(tree[x].d,xf,tree[x].faf); else xx=dist(tree[x].d,tree[x].faf,xf); if(tree[y].d%2==0)yy=dist(tree[y].d,tree[y].faf,yf); else yy=dist(tree[y].d,yf,tree[y].faf); xh=tree[x].wtcl-tree[xxx].wtcl; yh=2*pi*(ee[tree[y].d-1]-ee[tree[h].d])-(tree[y].wtcl-tree[yyy].wtcl); if(tree[h].d%2==0)hh=dist(tree[h].d,xxxx,yyyy); else hh=dist(tree[h].d,yyyy,xxxx); ans=xh+yh+xx+yy+hh;//分五段求和 if(ans>pi*(ee[tree[x].d]+ee[tree[y].d]-ee[tree[h].d]-ee[tree[h].d-1]))ans=2*pi*(ee[tree[x].d]+ee[tree[y].d]-ee[tree[h].d]-ee[tree[h].d-1])-ans;//最后再比较大小 printf("%.0lf\n",ans/pi);//输出 } return 0; }
- 1
信息
- ID
- 1204
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 2
- 已通过
- 2
- 上传者