Luogu

LOJ

分析

暴力就是把所有圆排序后直接 $\mathcal{O}(n^2)$ 模拟。

考虑用 KD-Tree 优化模拟过程。

我们把每个圆看作它的外接矩形,然后对于当前删去的圆在 KD-Tree 上递归,如果圆与矩形没有交则不会更新,可以直接返回。

然后建树时按方差选维度就可以过了。

代码

// ===================================
//   author: M_sea
//   website: http://m-sea-blog.com/
// ===================================
#include <bits/stdc++.h>
#define re register
#define sqr(x) (1ll*(x)*(x))
using namespace std;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=300000+10;

int n,ans[N];

#define ls t[o].lc
#define rs t[o].rc
int D,tot=0,rt;
struct point { int x[2],r,id; } p[N];
bool operator <(point a,point b) { return a.x[D]<b.x[D]; }
struct node { int mn[2],mx[2],lc,rc,sz; point p; } t[N];
inline int newnode() { return ++tot; }
inline void pushup(int o) {
    for (re int i=0;i<2;++i) {
        t[o].mn[i]=t[o].p.x[i]-t[o].p.r;
        t[o].mx[i]=t[o].p.x[i]+t[o].p.r;
        if (ls) {
            t[o].mn[i]=min(t[o].mn[i],t[ls].mn[i]);
            t[o].mx[i]=max(t[o].mx[i],t[ls].mx[i]);
        }
        if (rs) {
            t[o].mn[i]=min(t[o].mn[i],t[rs].mn[i]);
            t[o].mx[i]=max(t[o].mx[i],t[rs].mx[i]);
        }
    }
    t[o].sz=t[ls].sz+t[rs].sz+1;
}
inline int getd(int l,int r) {
    double s[2]={0,0};
    for (re int i=0;i<2;++i) {
        double ave=0;
        for (re int j=l;j<=r;++j) ave+=p[j].x[i];
        ave/=(r-l+1);
        for (re int j=l;j<=r;++j) s[i]+=(p[j].x[i]-ave)*(p[j].x[i]-ave);
    }
    return s[0]<s[1];
}
inline int build(int l,int r) {
    if (l>r) return 0;
    int o=newnode(),mid=(l+r)>>1;
    D=getd(l,r),nth_element(p+l,p+mid,p+r+1),t[o].p=p[mid];
    ls=build(l,mid-1),rs=build(mid+1,r);
    pushup(o); return o;
}
inline int out(node t,point p) {
    for (re int i=0;i<2;++i)
        if (p.x[i]+p.r<t.mn[i]||p.x[i]-p.r>t.mx[i]) return 1;
    return 0;
}
inline int inter(point a,point b) {
    return sqr(a.x[0]-b.x[0])+sqr(a.x[1]-b.x[1])<=sqr(a.r+b.r);
}
inline void query(int o,point p) {
    if (!ans[t[o].p.id]&&inter(p,t[o].p)) ans[t[o].p.id]=p.id;
    if (ls&&t[ls].sz&&!out(t[ls],p)) query(ls,p);
    if (rs&&t[rs].sz&&!out(t[rs],p)) query(rs,p);
    t[o].sz=t[ls].sz+t[rs].sz+!ans[t[o].p.id];
}
#undef ls
#undef rs

inline int cmp(point a,point b) {
    return a.r!=b.r?a.r>b.r:a.id<b.id;
}

int main() {
    n=read();
    for (re int i=1;i<=n;++i)
        p[i].x[0]=read(),p[i].x[1]=read(),p[i].r=read(),p[i].id=i;
    rt=build(1,n);
    sort(p+1,p+n+1,cmp);
    for (re int i=1;i<=n;++i) if (!ans[p[i].id]) query(rt,p[i]);
    for (re int i=1;i<=n;++i) printf("%d%c",ans[i]," \n"[i==n]);
    return 0;
}
最后修改:2021 年 03 月 24 日 05 : 03 PM