考虑和一个圆有交集的圆,是平面上的一块区域,所以我们考虑用 KDtree 维护。
两个圆相交的条件 \displaystyle (X_i-X_j)^2+(Y_i-Y_j)^2 \leqslant (R_i+R_j)^2
考虑怎么剪枝,直接维护 X,Y,R 的话不好维护。我们知道圆 i 和圆 j 有交集的话肯定会和框住圆 j 的最小的正方形有交集。
所以我们维护 KDtree 一个子树里所有圆对应的正方形 X,Y 的最值来剪枝即可。
yuan 里的 l,r :对应的正方形的左下角和右上角的坐标。
shu 里的 l,r :子树里正方形 x,y 坐标的最小值和最大值。
#include<algorithm>
#include<iostream>
#include<cstdio>
#define int long long
#define lson tr[k].ls
#define rson tr[k].rs
using namespace std;
int n, nowk, cnt, root;
const int N = 300010;
int s[N], ans[N];
struct dian {int x, y;};
struct yuan {int x, y, R, id; dian l, r;} cir[N];
struct shu {int ls, rs, id; dian l, r;} tr[N];
int my1(yuan a, yuan b) {return a.R == b.R ? a.id<b.id: a.R>b.R;}
int my2(int a, int b) {return nowk ? cir[a].x < cir[b].x : cir[a].y < cir[b].y;}
void pushup(int k)
{
tr[k].l = cir[tr[k].id].l; tr[k].r = cir[tr[k].id].r;
if (lson)tr[k].l.x = min(tr[k].l.x, tr[lson].l.x), tr[k].l.y = min(tr[k].l.y, tr[lson].l.y), tr[k].r.x = max(tr[k].r.x, tr[lson].r.x), tr[k].r.y = max(tr[k].r.y, tr[lson].r.y);
if (rson)tr[k].l.x = min(tr[k].l.x, tr[rson].l.x), tr[k].l.y = min(tr[k].l.y, tr[rson].l.y), tr[k].r.x = max(tr[k].r.x, tr[rson].r.x), tr[k].r.y = max(tr[k].r.y, tr[rson].r.y);
}
void build(int &k, int l, int r, int now)
{
if (l > r)return;
int mid = (l + r) >> 1;
nowk = now; nth_element(s + l, s + mid, s + r + 1, my2);
k = ++cnt; tr[k].id = s[mid];
build(lson, l, mid - 1, now ^ 1); build(rson, mid + 1, r, now ^ 1);
pushup(k);
}
int p2(int x) {return x * x;}
int jiao(int i, int j) {return p2(cir[i].x - cir[j].x) + p2(cir[i].y - cir[j].y) <= p2(cir[i].R + cir[j].R);}
void change(int k, int id)
{
if (!k)return;
if (cir[id].r.x < tr[k].l.x || tr[k].r.x < cir[id].l.x || cir[id].r.y < tr[k].l.y || tr[k].r.y < cir[id].l.y)return;
if (!ans[cir[tr[k].id].id] && jiao(tr[k].id, id))ans[cir[tr[k].id].id] = cir[id].id;
if (lson)change(lson, id); if (rson)change(rson, id);
}
signed main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
{
scanf("%lld%lld%lld", &cir[i].x, &cir[i].y, &cir[i].R);
cir[i].l.x = cir[i].x - cir[i].R; cir[i].l.y = cir[i].y - cir[i].R; cir[i].r.x = cir[i].x + cir[i].R; cir[i].r.y = cir[i].y + cir[i].R;
cir[i].id = i; s[i] = i;
}
sort(cir + 1, cir + 1 + n, my1); build(root, 1, n, 0);
for (int i = 1; i <= n; ++i)
if (!ans[cir[i].id])change(root, i);
for (int i = 1; i <= n; ++i)printf("%lld ", ans[i]);
return 0;
}
然而 uoj 和 loj 上有 hack 数据,我们只要充分发挥人类智慧旋转一下坐标系就行了。记得开 long \space double.代码在这
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· DeepSeek+PageAssist实现本地大模型联网
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· 从 14 秒到 1 秒:MySQL DDL 性能优化实战