LOJ2586 APIO2018 选圆圈
考前挣扎
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 选圆圈的更多相关文章
- 「APIO2018选圆圈」
「APIO2018选圆圈」 题目描述 在平面上,有 \(n\) 个圆,记为 \(c_1, c_2, \ldots, c_n\) .我们尝试对这些圆运行这个算法: 找到这些圆中半径最大的.如果有多个半径 ...
- BZOJ5465 APIO2018选圆圈(KD-Tree+堆)
考虑乱搞,用矩形框圆放KD-Tree上,如果当前删除的圆和矩形有交就递归下去删.为防止被卡,将坐标系旋转一定角度即可.注意eps稍微设大一点,最好开上long double. #include< ...
- [BZOJ5465][APIO2018]选圆圈(KD-Tree)
题意:给你n个圆,每次选择半径最大的,将它和与它相交的圆全部删去,输出每个圆是在哪次被删的. KD树模板题.用一个矩形框住这个圆,就可以直接剪枝了.为了防止被卡可以将点旋转一个角度,为了保险还可以多转 ...
- 【LG4631】[APIO2018]Circle selection 选圆圈
[LG4631][APIO2018]Circle selection 选圆圈 题面 洛谷 题解 用\(kdt\)乱搞剪枝. 维护每个圆在\(x.y\)轴的坐标范围 相当于维护一个矩形的坐标范围为\([ ...
- 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)
Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...
- 【LOJ2586】【APIO2018】选圆圈 CDQ分治 扫描线 平衡树
题目描述 在平面上,有 \(n\) 个圆,记为 \(c_1,c_2,\ldots,c_n\) .我们尝试对这些圆运行这个算法: 找到这些圆中半径最大的.如果有多个半径最大的圆,选择编号最小的.记为 \ ...
- 【loj2586】【APIO2018】选圆圈
题目 有 \(n\) 个圆$c_1,c_2, \cdots , c_n $,执行如下的操作: 找到剩下的半径最大的圆删除并删除所有和它有交的其他并没有被删除的圆: 求每个圆是被那个圆删除的: $1 \ ...
- [loj2586]选圆圈
下面先给出比较简单的KD树的做法-- 根据圆心建一棵KD树,然后模拟题目的过程,考虑搜索一个圆 剪枝:如果当前圆[与包含该子树内所有圆的最小矩形]都不相交就退出 然而这样的理论复杂度是$o(n^2)$ ...
- LOJ 2586 「APIO2018」选圆圈——KD树
题目:https://loj.ac/problem/2586 只会 19 分的暴力. y 都相等,仍然按直径从大到小做.如果当前圆没有被删除,那么用线段树把 [ x-r , x+r ] 都打上它的标记 ...
随机推荐
- CF1073G Yet Another LCP Problem 后缀自动机 + 虚树 + 树形DP
题目描述 记 $lcp(i,j)$ 表示 $i$ 表示 $i$ 这个后缀和 $j$ 这个后缀的最长公共后缀长度给定一个字符串,每次询问的时候给出两个正整数集合 $A$ 和 $B$,求$\sum_{i\ ...
- js点击获取—通过JS获取图片的绝对对坐标位置
一.通过JS获取鼠标点击时图片的相对坐标位置 源代码如下所示: <!DOCTYPE html> <html lang="en"> <head> ...
- Hadoop ”No room for reduce task“问题处理
早上发现一个任务有20个reduce,但是只有四个正常完成,剩余16个等待了8个小时才分配执行(集群槽位资源充足) 解决方法:查看了集群的log,发现有这种warn: -- ::, WARN org. ...
- HDU6599:求本质不同的子串(回文串)长度及数量
目录 hdu6599题意: manacher+后缀自动机+倍增 \(O(nlog(n))\) manacher+后缀数组+二分 \(O(nlog(n))\) 回文树(回文自动机) \(O(n)\) @ ...
- HDU6672 Seq(找规律)
HDU6672 Seq 对于递推式 \(a_n = (\sum_{i = 1}^{n-1}a_i * i)\%n\) 打表列出 \(a_i\) 的前 \(100\) 项,发现有以 \(6\) 为循环的 ...
- VS code 同步设置与插件
准备工作:拥有一个github账户,电脑上需安装VSCode.实现同步的功能主要依赖于VSCode插件 "Settings Sync"第一步:安装同步插件Settings Sync ...
- 127、TensorFlow 计算图执行(二)
import tensorflow as tf # Define a placeholder that expects a vector of three floating-point values ...
- Myeclipse优化配置
#utf8 (do not remove)#utf8 (do not remove)-startup../Common/plugins/org.eclipse.equinox.launcher_1.2 ...
- Linux运维工程师需掌握的技能
笔者是运维工程师,对Linux方面有点心得,现在说一下需要掌握哪方面的工具吧.说到工具,在行外可以说是技能,在行内我们一般称之为工具,就是运维必须要掌握的工具.我就大概列出这几方面,这样入门就基本没有 ...
- 设计模式 - 门面模式(Facade Pattern,也叫外观模式)
简介 场景 将系统划分为若干个子系统有利于降低系统的复杂性,但是这会增加调用者的复杂性.通过引入 Facade 可以对调用者屏蔽系统内部子系统的细节. Java 中有多个日志库,例如 log4j.lo ...