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

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define N 300010
#define double long double
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
const double PI=acos(-1.0);
const double eps=1E-;
int n,c,cnt,root,ans[N];
struct circle
{
double d[];int r,i;
bool operator <(const circle&a) const
{
return d[c]<a.d[c];
}
void rotate(double alpha)
{
double u=d[]*cos(alpha)-d[]*sin(alpha);
double v=d[]*sin(alpha)+d[]*cos(alpha);
d[]=u,d[]=v;
}
}a[N];
struct KDTree{int ch[];double a[][];circle p;
}tree[N];
double sqr(double x){return x*x;}
bool iscross(circle x,circle y){return sqr(x.d[]-y.d[])+sqr(x.d[]-y.d[])<sqr(x.r+y.r)+eps;}
double max(double x,double y,double z){return max(max(x,y),z);}
double iscross(circle p,double a[][]){return sqr(max(p.d[]-a[][],a[][]-p.d[],(double)))+sqr(max(p.d[]-a[][],a[][]-p.d[],(double)))<sqr(p.r)+eps;}
void build(int &k,int l,int r,int op)
{
if (l>r) return;
k=++cnt,c=op;int mid=l+r>>;nth_element(a+l,a+mid,a+r+);
tree[k].p=a[mid];
tree[k].a[][]=a[mid].d[]-a[mid].r,tree[k].a[][]=a[mid].d[]+a[mid].r,
tree[k].a[][]=a[mid].d[]-a[mid].r,tree[k].a[][]=a[mid].d[]+a[mid].r;
for (int i=l;i<=r;i++)
tree[k].a[][]=min(tree[k].a[][],a[i].d[]-a[i].r),tree[k].a[][]=max(tree[k].a[][],a[i].d[]+a[i].r),
tree[k].a[][]=min(tree[k].a[][],a[i].d[]-a[i].r),tree[k].a[][]=max(tree[k].a[][],a[i].d[]+a[i].r);
build(tree[k].ch[],l,mid-,op^);
build(tree[k].ch[],mid+,r,op^);
}
void find(int k,circle x)
{
if (!ans[tree[k].p.i]&&iscross(tree[k].p,x)) ans[tree[k].p.i]=x.i;
if (tree[k].ch[]&&iscross(x,tree[tree[k].ch[]].a)) find(tree[k].ch[],x);
if (tree[k].ch[]&&iscross(x,tree[tree[k].ch[]].a)) find(tree[k].ch[],x);
}
struct cmp
{
bool operator ()(const circle&a,const circle&b) const
{
return a.r<b.r||a.r==b.r&&a.i>b.i;
}
};
priority_queue<circle,vector<circle>,cmp> q;
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5465.in","r",stdin);
freopen("bzoj5465.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++)
{
a[i].d[]=read(),a[i].d[]=read(),a[i].i=i,a[i].r=read();
a[i].rotate(PI/);
q.push(a[i]);
}
build(root,,n,);
while ()
{
while (!q.empty()&&ans[q.top().i]) q.pop();
if (q.empty()) break;
circle x=q.top();q.pop();ans[x.i]=x.i;
find(root,x);
}
for (int i=;i<=n;i++) printf("%d ",ans[i]);
return ;
}

BZOJ5465 APIO2018选圆圈(KD-Tree+堆)的更多相关文章

  1. BZOJ5465: [APIO 2018] 选圆圈(K-D Tree)

    题意 题目链接 Sol 下面是错误做法,正解请看这里 考虑直接用K-D tree模拟.. 刚开始想的是维护矩形最大最小值,以及子树中最大圆的位置,然后... 实际上最大圆的位置是不用维护的,直接把原序 ...

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

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

  3. 「APIO2018选圆圈」

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

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

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

  5. LOJ2586 APIO2018 选圆圈

    考前挣扎 KD树好题! 暴力模拟 通过kd树的结构把子树内的圈圈框起来 然后排个序根据圆心距 <= R1+R2来判断是否有交点 然后随便转个角度就可以保持优越的nlgn啦 卡精度差评 必须写ep ...

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

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

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

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

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

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

  9. 「APIO2018」选圆圈

    传送门 Description 有\(n\)个圆,每次找到这些圆中半径最大中的编号最小的圆,删除ta及与其有交集的所有圆. 对于每个圆,求出它是被哪一个圆删除的. Solution  K-D Tree ...

随机推荐

  1. Leetcode——338. 比特位计数

    题目描述:题目链接 对于求解一个十进制数转化为二进制时里面1的个数,可以先看一下概况: 十进制数 二进制数 1的个数 1 1    1 2 10 1 3 11   2 4 100 1 5 101 2 ...

  2. C++之C++的词法单位

    C++的字符集 ASCII码字符集是计算机中的常用字符集.它包括英文字母及阿拉伯数字等128个字符,存储一个ASCII码占用一个字节单元. 由于汉字处理的需要,又出现了汉字国标码等对应于不同语言的字符 ...

  3. .NetCore Session.Redis (转载)

    首先创建ASP.NET CORE Web项目,然后按如下顺序操作. 1.添加nuget程序包: Microsoft.AspNetCore.Session; Microsoft.AspNetCore.D ...

  4. HBase启动报错:ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet

    今天进入hbase shell中输入命令报错:ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is no ...

  5. 福慧双修&探险 BZOJ4398&BZOJ2407

    分析: 双倍经验(数据范围不同). 我们考虑,我们必定是从1走一条边到节点i,之后从i到j跑最短路,之后再从j到1走另一条边的情况下,不会重复,并且是答案.那么我们考虑预处理出pre[i]表示从1走到 ...

  6. final、finally、 finalize 有什么不同

    感觉这三者除了长得像也没啥可作为比较的,但是面试题中经常会出现这三者的比较,就简单总结一下. 1.final final 可以用来修饰类.方法和变量,修饰类的时候表示类是不可以被继承的,修饰方法的时候 ...

  7. libgdx学习记录25——Rectangle与Circle是否重叠

    Rect与Circle重叠有三种情况: 1. Rect至少有一个角在Circle里面 2. Circle与Rect的左边或右边相交,或者Circle在Rect内 3. Circle与Rect的顶边或底 ...

  8. CS190.1x-ML_lab1_review_student

    这是CS190.1x第一次作业,主要教你如何使用numpy.numpy可以说是python科学计算的基础包了,用途非常广泛.相关ipynb文件见我github. 这次作业主要分成5个部分,分别是:数学 ...

  9. [APIO2013]机器人[搜索、斯坦纳树]

    题意 题目链接 分析 记 g(d,x,y) 表示从 (x,y) 出发,方向为 d 到达的点,这个可以通过记忆化搜索求出,注意如果转移成环(此时向这个方向走没有意义)要特判. 记 f(l,r,x,y) ...

  10. 《Effective Java》学习笔记 —— 序列化

    Java的序列化API提供了一个框架,用来将对象编码成一个字节流(序列化,serializing),并从字节流中重新创建对象(反序列化, deserializing). 第74条 谨慎地实现Seria ...