1 条题解
-
0
自动搬运
来自洛谷,原作者为

浮尘ii
**搬运于
2025-08-24 21:41:31,当前版本为作者最后更新于2017-01-02 22:26:19,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
笔者的做法和下面几篇题解是一样的,在这里就不重复叙述了。这里介绍一下官方给出的做法。
##题目分析
把平面上每一个区域看作一个结点,最外层没有边界的区域也看作一个结点。如果一个区域刚好被另外一个区域直接包含,则连边。构成的图上做最短路径即可以得到40~60的分数。
又发现,上述得到的图是树结构的,在树上预处理好任意两点的最近公共祖先,之后的询问可以线形完成,这便可以得到满分。
##std
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; struct Point { ll x,y; Point(){} Point(ll _x,ll _y):x(_x),y(_y){} Point operator - (const Point &t)const { return Point(x-t.x,y-t.y); } ll len2() { return x*x+y*y; } }; struct Circle { Point o; ll r; Circle(){} Circle(Point _o,ll _r):o(_o),r(_r){} bool operator < (const Circle &t)const { return r<t.r; } bool contain(Point t) { return (t-o).len2()<r*r; } }c[8005]; struct Edge { int to,nxt; }edge[8005]; int head[8005],tot; void init() { memset(head,-1,sizeof(head)); tot=0; } void addedge(int u,int v) { edge[tot].to=v; edge[tot].nxt=head[u]; head[u]=tot++; } int fa[8005],dep[8005]; void dfs(int u,int la) { fa[u]=la; dep[u]=(la>=0 ? dep[la]+1 : 0); for(int i=head[u];~i;i=edge[i].nxt) dfs(edge[i].to,u); } int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld%lld%lld",&c[i].o.x,&c[i].o.y,&c[i].r); c[n++]=Circle(Point(0,0),200000000); sort(c,c+n); init(); for(int i=0;i<n-1;i++) for(int j=i+1;j<n;j++) if(c[j].contain(c[i].o)) { addedge(j,i); break; } dfs(n-1,-1); int m; scanf("%d",&m); for(int i=0;i<m;i++) { int u[2]; for(int j=0;j<2;j++) { Point p; scanf("%lld%lld",&p.x,&p.y); for(int k=0;k<n;k++) if(c[k].contain(p)) { u[j]=k; break; } } int res=0; while(u[0]!=u[1]) { if(dep[u[0]]>dep[u[1]])u[0]=fa[u[0]]; else u[1]=fa[u[1]]; res++; } printf("%d\n",res); } return 0; }##吐槽
这玩意又难写,常数又大(原题时限5s),不知道出题人怎么想到的。
- 1
信息
- ID
- 1807
- 时间
- 3000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者