考前挣扎

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. Web上传文件的三种解决方案

    第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname =  ...

  2. [CF846E]Chemistry in Berland题解

    这题乍一看是一道水树形DP(其实事实上它确实是树形DP),然后设f[i]表示第i个点所多余/需要的材料,然后我们愉快的列出了式子: if(f[v]<0) f[u] += f[v] * edges ...

  3. 洛谷 P4300 BZOJ 1266 [AHOI2006]上学路线route

    题目描述 可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校.直到有一天他们两人参加了学校的信息学奥林匹克竞赛小组才发现每天上学的乘车路线不一定是最优的. 可可:“很可能我们在 ...

  4. php面试专题---16、MySQL创建高性能索引考点

    php面试专题---16.MySQL创建高性能索引考点 一.总结 一句话总结: 注意:只写精品 1.索引的基础? 类似书籍的目录:索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录 ...

  5. EZOJ #373排序

    分析 它居然真的是个nlog^3暴力?! 两个数在加小于min(lowbit(x),lowbit(y))的数时对他们的奇偶性不影响 因此每次加上min(lowbit(x),lowbit(y))判断此时 ...

  6. P2239螺旋矩阵

    传送 看到这数据范围,显然咱不能暴力直接模拟(二维数组开不下,而且会T掉) 我们目前有两种选择: 1.优化暴力  走这边(jyy tql%%%) 2.数学做法 我们看一下题目中的那个矩阵 我们能不能找 ...

  7. Jenkins使用一:CentOS7安装Jenkins

    安装jdk环境: yum search jdk 装 1.8版本的:yum install -y java-1.8.0-openjdk 安装Jenkins wget -O /etc/yum.repos. ...

  8. Iterator 和 ListIterator 对比

    Iterator 的方法 //是否还有下一个 boolean hasNext(); //返回下一个 E next(); //移除返回的下一个 void remove(); ListIterator 的 ...

  9. 第1 章 mysql数据库之简单的DDL和DML sql语句

    一.SQL 介绍 1.什么是sql? SQL,英文全称(Structured Query Language),中文是结构化查询语言,它是一种对关系数据库中数据进行定义和操作的语言方法,是大多数关系数据 ...

  10. php json_encode的问题

    问题:跨域调用信息,返回json格式数据,返回的json数据中会多出空格,导致再用json_decode()编码的时候,页面显示空白,编码失败.解决方法:在页面中加入ob_end_clean();解决 ...