考前挣扎

KD树好题!

暴力模拟 通过kd树的结构把子树内的圈圈框起来

然后排个序根据圆心距 <= R1+R2来判断是否有交点

然后随便转个角度就可以保持优越的nlgn啦

卡精度差评 必须写eps差评

//Love and Freedom.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define db long double
#define inf 20021225
#define ll long long
#define mxn 310000
#define eps 1e-3
using namespace std; struct poi
{
db x,y;
poi(){}
poi(db _x,db _y){x=_x,y=_y;}
}; struct circle
{
db r; poi pos; int id;
circle(){}
circle(poi _pos,db _r){pos=_pos;r = _r;}
}cc[mxn];
int ans[mxn];
struct node
{
int son[2],id; //poi p;
db r,mr,mx[2],mn[2],pos[2];
};
bool flag;
bool cmp(circle a,circle b)
{
if(flag?abs(a.pos.x - b.pos.x)<eps:abs(a.pos.y-b.pos.y)<eps) return a.r>b.r;
return flag?a.pos.x<b.pos.x:a.pos.y<b.pos.y;
} db dis(poi a,poi b)
{
return (a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y);
}
struct KD
{
node t[mxn]; int rt;
void update(int x)
{
int l = t[x].son[0];
int r = t[x].son[1];
for(int c = 0;c < 2; c++)
{
if(l) t[x].mx[c]=max(t[l].mx[c],t[x].mx[c]),t[x].mn[c]=min(t[l].mn[c],t[x].mn[c]);
if(r) t[x].mx[c]=max(t[r].mx[c],t[x].mx[c]),t[x].mn[c]=min(t[r].mn[c],t[x].mn[c]);
}
if(l) t[x].mr=max(t[x].mr,t[l].mr);
if(r) t[x].mr=max(t[x].mr,t[r].mr);
}
void build(int &x,int l,int r,bool w)
{
flag = w; sort(cc+l,cc+r+1,cmp);
int mid = l+r>>1; x = mid;
t[x].mr = t[x].r = cc[mid].r; t[x].id = cc[mid].id;
for(int c = 0;c < 2;c++)
t[x].pos[c] = t[x].mn[c] = t[x].mx[c] = c?cc[mid].pos.y:cc[mid].pos.x;
if(l<mid) build(t[x].son[0],l,mid-1,w^1);
if(mid<r) build(t[x].son[1],mid+1,r,w^1);
update(x);
}
bool del(circle goal, circle tmp)
{
if(dis(goal.pos,tmp.pos) - (goal.r+tmp.r)*(goal.r+tmp.r)<=eps) return true;
return false;
}
db check(int x,circle goal)
{
db ans = 0;
for(int c = 0;c < 2;c++)
{
db wz = (c?goal.pos.y:goal.pos.x),tmp;
if(wz>=t[x].mn[c] && wz<=t[x].mx[c]) tmp = 0;
else tmp = min(abs(t[x].mn[c]-wz),abs(t[x].mx[c]-wz));
ans += tmp*tmp;
}
return ans;
}
void query(int x,circle goal,int w)
{
if(!ans[t[x].id] && del(goal,circle(poi(t[x].pos[0],t[x].pos[1]),t[x].r))) ans[t[x].id] = w;
int l = t[x].son[0], r = t[x].son[1]; db d1,d2;
if(l)
{
d1 = check(l,goal);
if((t[l].mr+goal.r)*(t[l].mr+goal.r) -d1>= -eps) query(l,goal,w);
}
if(r)
{
d2 = check(r,goal);
if((t[r].mr+goal.r)*(t[r].mr+goal.r) -d2>= -eps) query(r,goal,w);
}
}
}kd;
bool qaq(circle a,circle b)
{
return abs(a.r-b.r)<eps?a.id<b.id:a.r>b.r;
} const db phi = 1.05426;
poi rotate(poi a)
{
return poi(cosl(phi)*a.x-sinl(phi)*a.y,sinl(phi)*a.x+cosl(phi)*a.y);
} int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%Lf%Lf%Lf",&cc[i].pos.x,&cc[i].pos.y,&cc[i].r),cc[i].id=i;
cc[i].pos = rotate(cc[i].pos);
}
kd.build(kd.rt,1,n,0);
sort(cc+1,cc+n+1,qaq);
for(int i=1;i<=n;i++)
if(!ans[cc[i].id])
kd.query(kd.rt,cc[i],cc[i].id);
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
return 0;
}

LOJ2586 APIO2018 选圆圈的更多相关文章

  1. 「APIO2018选圆圈」

    「APIO2018选圆圈」 题目描述 在平面上,有 \(n\) 个圆,记为 \(c_1, c_2, \ldots, c_n\) .我们尝试对这些圆运行这个算法: 找到这些圆中半径最大的.如果有多个半径 ...

  2. BZOJ5465 APIO2018选圆圈(KD-Tree+堆)

    考虑乱搞,用矩形框圆放KD-Tree上,如果当前删除的圆和矩形有交就递归下去删.为防止被卡,将坐标系旋转一定角度即可.注意eps稍微设大一点,最好开上long double. #include< ...

  3. [BZOJ5465][APIO2018]选圆圈(KD-Tree)

    题意:给你n个圆,每次选择半径最大的,将它和与它相交的圆全部删去,输出每个圆是在哪次被删的. KD树模板题.用一个矩形框住这个圆,就可以直接剪枝了.为了防止被卡可以将点旋转一个角度,为了保险还可以多转 ...

  4. 【LG4631】[APIO2018]Circle selection 选圆圈

    [LG4631][APIO2018]Circle selection 选圆圈 题面 洛谷 题解 用\(kdt\)乱搞剪枝. 维护每个圆在\(x.y\)轴的坐标范围 相当于维护一个矩形的坐标范围为\([ ...

  5. 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)

    Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...

  6. 【LOJ2586】【APIO2018】选圆圈 CDQ分治 扫描线 平衡树

    题目描述 在平面上,有 \(n\) 个圆,记为 \(c_1,c_2,\ldots,c_n\) .我们尝试对这些圆运行这个算法: 找到这些圆中半径最大的.如果有多个半径最大的圆,选择编号最小的.记为 \ ...

  7. 【loj2586】【APIO2018】选圆圈

    题目 有 \(n\) 个圆$c_1,c_2, \cdots , c_n $,执行如下的操作: 找到剩下的半径最大的圆删除并删除所有和它有交的其他并没有被删除的圆: 求每个圆是被那个圆删除的: $1 \ ...

  8. [loj2586]选圆圈

    下面先给出比较简单的KD树的做法-- 根据圆心建一棵KD树,然后模拟题目的过程,考虑搜索一个圆 剪枝:如果当前圆[与包含该子树内所有圆的最小矩形]都不相交就退出 然而这样的理论复杂度是$o(n^2)$ ...

  9. LOJ 2586 「APIO2018」选圆圈——KD树

    题目:https://loj.ac/problem/2586 只会 19 分的暴力. y 都相等,仍然按直径从大到小做.如果当前圆没有被删除,那么用线段树把 [ x-r , x+r ] 都打上它的标记 ...

随机推荐

  1. 51nod 1205 流水线调度

    1205 流水线调度 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 N个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工.每个 ...

  2. 使用debugger在程序中加入断点

    使用debugger在程序中加入断点 版权声明:本文为博主原创文章,未经博主允许不得转载. 我们可以在程序中加入debugger语句,这样Firefox的调试工具会停留在这条语句上,代码也暂停执行,和 ...

  3. 初步学习JS中的闭包

    JS高级程序设计(3rd)中对闭包的定义就是一句话,首先闭包是一个函数,怎样的函数呢?有权访问另一个函数作用域中的变量 的函数.而创建闭包的常见方式就是在一个函数的内部创建另一个函数,就是嵌套函数. ...

  4. SPSS输出结果如何在word中设置小数点前面显示加0

    SPSS输出结果如何在word中设置小数点前面显示加0 在用统计分析软件做SPSS分析时,其输出的结果中,如果是小于1(绝对值)的数,那么会默认输出不带小数点的数值.例如0.362和 -0.141被显 ...

  5. 第 1 章 前端之html

    一.html初始 1.web服务本质 import socket def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM ...

  6. response.getWriter()和jsp中的out对象的区别

    (1) out和response.getWriter属于的类不同,前者是JspWriter,后者是java.io.PrintWriter.而JspWriter是一个抽象类, PrintWriter是一 ...

  7. [BZOJ3622] 已经没有什么好害怕的了(dp+容斥)

    Description: ​ 有两个数组a和b,两两配对,求 \(a_i>b_i\) 的配对比 \(b_i>a_i\) 的配对多 \(k\) 个的方案数 \(k\le n\le 2000\ ...

  8. spring(三):spring中BeanPostProcessor的使用

    spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...

  9. Linux筛选数据

    grep命令:在文件中查找关键字,并显示所在行(Globally search a Regular Expression and Print) grep text file:在file文件中搜索tex ...

  10. python 异常处理【转载】

    什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Python脚本 ...