传送门

那个当前半径最大的圆可以用堆维护.这道题一个想法就是优化找和当前圆有交的圆的过程.考虑对于所有圆心建KD-tree,然后在树上遍历的找这样的点.只要某个点子树内的点构成的矩形区域到当前圆心的最近距离\(>2\)倍半径就不用找了

然而在loj上过不去,这时就可以用一个很鸡贼的优化,对于所有点绕原点旋转一定角度,然后就跑的过了(可能是全在一条直线上建KD-tree会出锅(雾)).稍微注意精度误差就行了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double using namespace std;
const int N=3e5+10;
const LL inf=1ll<<61;
const db eps=1e-3,tpd=sqrt(2)/2;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int nd;
struct point
{
db d[2];
int i;
bool operator < (const point &bb) const {return fabs(d[nd]-bb.d[nd])>eps?d[nd]<bb.d[nd]:i<bb.i;}
}a[N],b[N],qwq;
struct cir
{
point p;
db r;
bool operator < (const cir &bb) const {return fabs(r-bb.r)>eps?r<bb.r:p.i>bb.p.i;}
}c[N];
priority_queue<cir> hp;
int n,m,rt,ch[N][2],an[N],ii;
db mx[N][2],my[N][2];
void bui(int &o,int l,int r,int nnd)
{
if(l>r) return;
if(l==r)
{
o=b[l].i;
mx[o][0]=mx[o][1]=a[o].d[0];
my[o][0]=my[o][1]=a[o].d[1];
return;
}
int mid=(l+r)>>1;
nd=nnd;
nth_element(b+l,b+mid,b+r+1);
o=b[mid].i;
mx[o][0]=mx[o][1]=a[o].d[0];
my[o][0]=my[o][1]=a[o].d[1];
bui(ch[o][0],l,mid-1,nnd^1);
bui(ch[o][1],mid+1,r,nnd^1);
mx[o][0]=min(mx[o][0],min(mx[ch[o][0]][0],mx[ch[o][1]][0]));
mx[o][1]=max(mx[o][1],max(mx[ch[o][0]][1],mx[ch[o][1]][1]));
my[o][0]=min(my[o][0],min(my[ch[o][0]][0],my[ch[o][1]][0]));
my[o][1]=max(my[o][1],max(my[ch[o][0]][1],my[ch[o][1]][1]));
}
db dis(point aa,point bb){return (aa.d[0]-bb.d[0])*(aa.d[0]-bb.d[0])+(aa.d[1]-bb.d[1])*(aa.d[1]-bb.d[1]);}
db expt(int o)
{
if(!o) return inf;
db xx=min(mx[o][1]-qwq.d[0],qwq.d[0]-mx[o][0])<-eps?min(fabs(mx[o][1]-qwq.d[0]),fabs(qwq.d[0]-mx[o][0])):0;
db yy=min(my[o][1]-qwq.d[1],qwq.d[1]-my[o][0])<-eps?min(fabs(my[o][1]-qwq.d[1]),fabs(qwq.d[1]-my[o][0])):0;
return xx*xx+yy*yy;
}
void wk(int o)
{
if(!o||expt(o)>(db)qwq.i*(db)qwq.i+eps) return;
if(!an[o])
{
db rr=(db)qwq.i/2+c[o].r;
if(dis(a[o],qwq)<rr*rr+eps) an[o]=ii;
}
wk(ch[o][0]),wk(ch[o][1]);
} int main()
{
n=rd();
for(int i=1;i<=n;++i)
{
db xx=rd(),yy=rd();
a[i].d[0]=tpd*xx+tpd*yy,a[i].d[1]=tpd*yy-tpd*xx;
a[i].i=i;
b[i]=a[i];
c[i].p=a[i],c[i].r=rd();
hp.push(c[i]);
}
mx[0][0]=my[0][0]=inf,mx[0][1]=my[0][1]=-inf;
bui(rt,1,n,0);
while("ji ni tai mei")
{
while(!hp.empty()&&an[hp.top().p.i]) hp.pop();
if(hp.empty()) break;
cir cc=hp.top();
hp.pop();
ii=cc.p.i;
qwq=cc.p,qwq.i=cc.r*2;
wk(rt);
}
for(int i=1;i<=n;++i) printf("%d ",an[i]);
return 0;
}

luogu P4631 [APIO2018] Circle selection 选圆圈的更多相关文章

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

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

  2. [Luogu4631][APIO2018] Circle selection 选圆圈

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

  3. [APIO2018] Circle selection 选圆圈(假题解)

    题面 自己去\(LOJ\)上找 Sol 直接排序然后\(KDTree\)查询 然后发现\(TLE\)了 然后把点旋转一下,就过了.. # include <bits/stdc++.h> # ...

  4. [APIO2018] Circle selection 选圆圈

    Description 给出 \(n\) 个圆 \((x_i,y_i,r_i)\) 每次重复以下步骤: 找出半径最大的圆,并删除与这个圆相交的圆 求出每一个圆是被哪个圆删除的 Solution \(k ...

  5. 洛谷4631 [APIO2018] Circle selection 选圆圈 (KD树)

    qwq纪念AC450 一开始想这个题想复杂了. 首先,正解的做法是比较麻烦的. qwqq 那么就不如来一点暴力的东西,看到平面上点的距离的题,不难想到\(KD-Tree\) 我们用类似平面最近点对那个 ...

  6. [APIO2018]Circle selection

    https://www.zybuluo.com/ysner/note/1257597 题面 在平面上,有\(n\)个圆,记为\(c_1,c_2,...,c_n\).我们尝试对这些圆运行这个算法: 找到 ...

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

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

  8. 「APIO2018选圆圈」

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

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

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

随机推荐

  1. Unity3D_(游戏)贪吃蛇

    Unity制作贪吃蛇小游戏 玩家通过“WASD”控制小蛇上下左右移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自己身体游戏结束 可通 ...

  2. vue 移动端的开发

    一:cli 的安装: cnpm install -g @vue/cli默认是安装在如下目录:C:\Users\xiaocj\AppData\Roaming\npm\node_modules\@vue ...

  3. C++入门经典-例5.12-动态内存的销毁

    1:当申请一块堆内存后,系统不会再程序执行时一句情况自动销毁它.若想释放该内存,则需要使用delete关键字.下面的代码中,可以看出堆和栈的不同.代码如下: // 5.12.cpp : 定义控制台应用 ...

  4. 剑指offer:把一个支付算转化为整数

    1:首先,根据课本上的程序,是这样的: #include "stdafx.h" #include "iostream" using namespace std; ...

  5. python3笔记二十三:正则表达式之其他函数

    一:学习内容 re.split函数 re.finditer函数 re.sub函数 group()分组 re.compile函数 二:字符串切割---re.split函数 需要导入包:import re ...

  6. Python学习笔记:类

    类可以将数据与函数封装起来,用一个例子解释,先定义一个类: class athlete: def __init__(self,a_name,a_dob=None,a_times=[]): self.n ...

  7. your current language level is ecmascript 5

    https://stackoverflow.com/questions/32995066/how-can-i-configure-resharpers-language-level-for-ecmas ...

  8. shell sed应用

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为:sed [-nefri] ...

  9. java远程调用中出现的问题(主要是在不同电脑之间出现的问题)

    1.在运行远程服务端之前,使用rmic命令操作impl 2.运行客户端出现time out,尝试ping服务器电脑不能成功.关闭服务器端防火墙,可ping成功. 3.显示连接失败,错误显示的ip不是自 ...

  10. 如何手写实现简易的Dubbo[z]

    [z]https://juejin.im/post/5ccf8dec6fb9a0321c45ebb5 前言 结束了集群容错和服务发布原理这两个小专题之后,有朋友问我服务引用什么时候开始,本篇为服务引用 ...