题目

有 \(n\) 个圆$c_1,c_2, \cdots , c_n $,执行如下的操作:

找到剩下的半径最大的圆删除并删除所有和它有交的其他并没有被删除的圆;

求每个圆是被那个圆删除的;

$1 \le n \le 3 \times 10^5 $ ;

描述

  • kdt做法:

    记录每个圆围成的举行作为剪枝,直接模拟删除;

    记得旋转一下,然后eps开1e-3就好;

  • 搬运一下$n \ log^2n $做法(orz yww):

    考虑找到和\(c_i\) 相交的半径最大的被自己删除的圆 ;

    这样的圆一定满足互相不相交;

    由于半径比 \(c_i\) 大,所以如果相交一定会和 \(c_i\) 平行坐标轴的四条切线有交;

    所以用扫描线+cdq分治即可;

    //懒得写正解了这是暴力:
    #include<bits/stdc++.h>
    #define eps 1e-3
    #define ld double
    using namespace std;
    const int N=300010;
    const ld sq2=sqrt(2);
    int n,WD,pos[N],bl[N],ls[N],rs[N],tr[N],rt;///
    struct P{ld x,y;};///
    ld mn[N][2],mx[N][2];///
    struct C{P o;ld r,mn[2],mx[2];int id;}c[N];///
    int dcmp(ld x){return fabs(x)<eps?0:x<0?-1:1;}///
    bool cmp(C A,C B){return !dcmp(A.r-B.r)?A.id<B.id:A.r>B.r;}///
    bool cmpD(int A,int B){return !WD?c[A].o.x<c[B].o.x:c[A].o.y<c[B].o.y;}///
    ld len(P A,P B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}///
    bool judge(C A,C B){return dcmp(len(A.o,B.o)-(A.r+B.r)*(A.r+B.r))<=0;}///
    void rotate(P&A){A=(P){(A.x-A.y)/sq2,(A.x+A.y)/sq2};}///
    char gc(){
    static char*p1,*p2,s[1000000];
    if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
    return(p1==p2)?EOF:*p1++;
    }///
    int rd(){
    int x=0,f=1;char C=gc();
    while(C<'0'||C>'9'){if(C=='-')f=-1;C=gc();}
    while(C>='0'&&C<='9'){x=x*10+C-'0';C=gc();}
    return x*f;
    }///
    void build(int&k,int l,int r,int d){
    WD=d;k=(l+r)>>1;
    nth_element(tr+l,tr+k,tr+r+1,cmpD);
    mn[k][0]=c[tr[k]].mn[0];
    mx[k][0]=c[tr[k]].mx[0];
    mn[k][1]=c[tr[k]].mn[1];
    mx[k][1]=c[tr[k]].mx[1];
    if(l<k){
    build(ls[k],l,k-1,d^1);
    for(int i=0;i<2;++i){
    mn[k][i]=min(mn[k][i],mn[ls[k]][i]);
    mx[k][i]=max(mx[k][i],mx[ls[k]][i]);
    }
    }
    if(k<r){
    build(rs[k],k+1,r,d^1);
    for(int i=0;i<2;++i){
    mn[k][i]=min(mn[k][i],mn[rs[k]][i]);
    mx[k][i]=max(mx[k][i],mx[rs[k]][i]);
    }
    }
    }///
    bool jud(int x,int y){return !x||mx[x][0]<c[y].mn[0]-eps||mn[x][0]>c[y].mx[0]+eps||mx[x][1]<c[y].mn[1]-eps||mn[x][1]>c[y].mx[1]+eps;}///
    void query(int k,int x){
    if(!bl[tr[k]]&&judge(c[tr[k]],c[x]))bl[tr[k]]=c[x].id;
    if(!jud(ls[k],x))query(ls[k],x);
    if(!jud(rs[k],x))query(rs[k],x);
    }///
    int main(){
    // freopen("B.in","r",stdin);
    // freopen("B.out","w",stdout);
    n=rd();
    for(int i=1;i<=n;++i){
    c[i].o.x=rd();c[i].o.y=rd();
    rotate(c[i].o);c[i].r=rd();
    c[i].mn[0]=c[i].o.x-c[i].r;
    c[i].mx[0]=c[i].o.x+c[i].r;
    c[i].mn[1]=c[i].o.y-c[i].r;
    c[i].mx[1]=c[i].o.y+c[i].r;
    c[i].id=tr[i]=i;
    }///
    sort(c+1,c+n+1,cmp);
    for(int i=1;i<=n;++i)pos[c[i].id]=i;
    build(rt,1,n,0);
    for(int i=1;i<=n;++i){
    if(!bl[i])query(rt,i);
    }
    for(int i=1;i<=n;++i)printf("%d ",bl[pos[i]]);
    return 0;//
    }//

【loj2586】【APIO2018】选圆圈的更多相关文章

  1. LOJ2586 APIO2018 选圆圈

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

  2. 「APIO2018选圆圈」

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

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

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

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

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

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

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

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

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

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

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

  8. [loj2586]选圆圈

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

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

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

随机推荐

  1. 基于openvswitch+Docker构建SDN网络测试环境 (使用ovs-docker进行构建)

    这是一篇之前写的笔记,主要记录了使用openvswitch + Docker 等进行一个小型的SDN网络搭建的操作步骤.由于 之前临时有其他任务,耽搁了一下,最近开始重新整理,并计划开发一个简单的Py ...

  2. Hands on Machine Learning with Sklearn and TensorFlow学习笔记——机器学习概览

    一.什么是机器学习? 计算机程序利用经验E(训练数据)学习任务T(要做什么,即目标),性能是P(性能指标),如果针对任务T的性能P随着经验E不断增长,成为机器学习.[这是汤姆米切尔在1997年定义] ...

  3. 【RL系列】Multi-Armed Bandit笔记补充(二)

    本篇的主题是对Upper Conference Bound(UCB)策略进行一个理论上的解释补充,主要探讨UCB方法的由来与相关公式的推导. UCB是一种动作选择策略,主要用来解决epsilon-gr ...

  4. 基于NABCD评论作业-王者荣耀交流协会PSP DAILY

    一.根据(不限于)NABCD评论作品的选题   N(Need,需求):在我知道PSP DAILY这款软件的时候,就认为这款软件对于学习软件工程课的学生来说有很大的需要.对于需求来说,软件工程课程中的学 ...

  5. 软件工程-东北师大站-第八次作业(PSP)

    1.本周PSP 2.本周进度条 3.本周累计进度图 代码累计折线图 博文字数累计折线图 4.本周PSP饼状图

  6. 团队项目-NABCD

    用户需求分析与NABCD 模拟经营类(SIM)游戏:玩家模拟经营一家软件公司,平台初步定为Android. Need需求 任何一款游戏都要有自己的定位和目标群体,这些 iiMediaResearch数 ...

  7. 关于echart柱形图的使用问题

    关于一个数据对应两个值的问题 series: [{ name: '数量(个)', type: 'bar', barWidth: '30%', barGap: , //两个数据条没有间距 data: y ...

  8. beat冲刺(3/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(3/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 整理博客 ppt模板 接下来的计划 做好机动. ...

  9. BNUOJ 52303 Floyd-Warshall Lca+bfs最短路

    题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52303 Floyd-Warshall Time Limit: 60000msMemory L ...

  10. CANOpen学习指南

    对于初学者,相对于其他总线的资料来说,在国内CANOpen的资料并不多.而且并不是所有资料都适合初学者看的.这里给出一些建议,对CANOpen感兴趣的,可以参考一下学习的顺序. 前提:需要对CAN总线 ...