【bzoj2961】共点圆 k-d树
更新:此题我的代码设置eps=1e-8会WA,现在改为1e-9貌似T了
此题网上的大部分做法是cdq分治+凸包,然而我觉得太烦了,于是自己口胡了一个k-d树做法:
加入一个圆$(x,y)$,直接在k-d树上加入这个点即可,注意要打rebuild否则会T。
查询一个点$(x_0,y_0)$是否在所有的圆上时:
我们设当前需要判断一个圆$(x,y)$是否覆盖该点,通过简单的分析,可以列出以下式子:
$(x-x_0)^2+(y-y_0)^2≤x_0^2+y_0^2$
我们不妨设$y_0>0$通过简单变式和移项,我们可以得到:
$y \geq -\frac{x_0}{y_0}x+\frac{x_0^2+y_0^2}{2y}$
我们将$ -\frac{x_0}{y_0} $和$ \frac{x_0^2+y_0^2}{2y} $视作常数,得到$y≤kx+b$,这是啥?一个半平面啊!!
问题即转化为了当前k-d树中是否所有点均在该半平面内,直接在k-d树中查询即可(实际上还需要有点思考量的分类讨论)
对于$y_0<0$的情况,部分符号需做些许更改。对于$y_0=0$的情况,需要特殊讨论!!(大概是$x<\frac{x_0}{2}$)
然后就没啦,时间复杂度$O(n log n+n^{1.5})$
PS:千万要记得打y=0的情况(我就被这个卡了很久)
#include<bits/stdc++.h>
#define M 500000
#define eps 1e-9
#define INF 1e20
using namespace std; #define MFLONG 13000000
#define NUM(x) ((48<=x&&x<=57)||x=='-')
char _c[MFLONG],_w[MFLONG]={};int _ns=,_nw=;int _x[],_ld;
inline void rd(int &_q){int _fu;if(_c[_ns]==) return;while(!NUM(_c[_ns])) _ns++;if(_c[_ns]=='-') _fu=-,_ns++;else _fu=;_q=;while(NUM(_c[_ns])) _q=_q*+_c[_ns++]-;_q=_fu*_q;}
inline void rd(double &X)
{
double x=,f=;
for (;_c[_ns]<''||_c[_ns]>'';_ns++) if (_c[_ns]=='-') f=-;
for (;_c[_ns]>=''&&_c[_ns]<='';_ns++) x=x*+_c[_ns]-'';
if (_c[_ns]!='.') {X=x*f;return;} _ns++;
for (double hh=0.1;_c[_ns]>=''&&_c[_ns]<='';_ns++,hh=hh/) x+=(_c[_ns]-'')*hh;
X=x*f;
} int D;
struct node{
double max[],min[],a[];
int l,r,siz;
node(){
max[]=max[]=a[]=a[]=l=r=siz=;
min[]=min[]=INF;
}
void clear(){
max[]=max[]=a[]=a[]=l=r=siz=;
min[]=min[]=INF;
}
node(double x,double y){
max[]=max[]=l=r=siz=;
min[]=min[]=INF;
a[]=x; a[]=y;
}
friend bool operator <(node a,node b){return a.a[D]<b.a[D];}
}a[M]; int root=,use=,reb=,rebfa=,rebd=; void insert(int &x,int fa,int d,node k){
if(!x){x=++use; a[x]=k;}
else{
if(k.a[d]<a[x].a[d]) insert(a[x].l,x,d^,k);
else insert(a[x].r,x,d^,k);
}
a[x].siz++;
a[x].max[]=max(a[x].max[],k.a[]); a[x].min[]=min(a[x].min[],k.a[]);
a[x].max[]=max(a[x].max[],k.a[]); a[x].min[]=min(a[x].min[],k.a[]);
if(max(a[a[x].l].siz,a[a[x].r].siz)>a[x].siz*0.77) reb=x,rebfa=fa,rebd=d;
} int id[M]={},cnt=;
bool cmp(int x,int y){return a[x]<a[y];}
void bl(int x){if(!x) return;id[++cnt]=x;bl(a[x].l); bl(a[x].r);}
void rebuild(int &x,int l,int r,int d){
if(l>r) {x=; return;}
int mid=(l+r)>>; D=d;
nth_element(id+l,id+mid,id+r+,cmp); x=id[mid];
a[x].max[]=a[x].min[]=a[x].a[];
a[x].max[]=a[x].min[]=a[x].a[];
rebuild(a[x].l,l,mid-,d^); rebuild(a[x].r,mid+,r,d^);
a[x].siz=a[a[x].l].siz+a[a[x].r].siz+;
for(int i=;i<;i++)
a[x].max[i]=max(a[x].max[i],max(a[a[x].l].max[i],a[a[x].r].max[i])),
a[x].min[i]=min(a[x].min[i],min(a[a[x].l].min[i],a[a[x].r].min[i]));
}
void rebuild(){
if(!reb) return;
bl(reb);
if(!rebfa) rebuild(root,,cnt,rebd);
else{
if(a[rebfa].l==reb) rebuild(a[rebfa].l,,cnt,rebd);
else rebuild(a[rebfa].r,,cnt,rebd);
}
cnt=reb=rebfa=;
} bool queryl(int x,double k,double b){
if(!x) return ;
if(k>&&a[x].max[]*k+b<a[x].min[]-eps) return ;
if(k>&&a[x].min[]*k+b>=a[x].max[]) return ;
if(k>&&a[x].a[]*k+b<a[x].a[]+eps) return ; if(k<=&&a[x].max[]*k+b>=a[x].max[]-eps) return ;
if(k<=&&a[x].min[]*k+b<a[x].min[]) return ;
if(k<=&&!(a[x].a[]*k+b>a[x].a[]-eps)) return ; return queryl(a[x].l,k,b)&queryl(a[x].r,k,b);
} bool queryr(int x,double k,double b){
if(!x) return ;
if(k>&&a[x].max[]*k+b<a[x].min[]) return ;
if(k>&&a[x].min[]*k+b>a[x].max[]-eps) return ;
if(k>&&a[x].a[]*k+b>a[x].a[]-eps) return ; if(k<=&&a[x].max[]*k+b>a[x].max[]) return ;
if(k<=&&a[x].min[]*k+b<a[x].min[]+eps) return ;
if(k<=&&!(a[x].a[]*k+b<a[x].a[]+eps)) return ; return queryr(a[x].l,k,b)&queryr(a[x].r,k,b);
} bool queryx(int x,int k,double l){
if(!x) return ;
if(k>&&l<=a[x].min[]+eps) return ;
if(k>&&l>a[x].max[]-eps) return ;
if(k>&&l>a[x].a[]-eps) return ; if(k<&&a[x].max[]-eps<=l) return ;
if(k<&&l<a[x].min[]+eps) return ;
if(k<&&l>a[x].a[]) return ; return queryx(a[x].l,k,l)&queryx(a[x].r,k,l);
} int main(){
//fread(_c,1,MFLONG,stdin);
int n; //rd(n);
scanf("%d",&n);
while(n--){
int op; double x,y;
//rd(op);rd(x);rd(y);
scanf("%d%lf%lf",&op,&x,&y);
if(op==){
insert(root,,,node(x,y));
rebuild();
}else{
if(fabs(y)<=eps&&fabs(x)<=eps){
printf("Yes\n");
continue;
}
if(fabs(y)<eps){
bool ck=queryx(root,(x>?:-),(x*x)/x/.);
if(ck&&use) puts("Yes"); else puts("No");
continue;
}
bool ck; double k,b;
b=(x*x+y*y)/(*y); k=-x/y;
if(y<) ck=queryl(root,k,b);
else ck=queryr(root,k,b);
if(ck&&use) puts("Yes"); else puts("No");
}
}
}
【bzoj2961】共点圆 k-d树的更多相关文章
- BZOJ2961 共点圆[CDQ分治]
题面 bzoj 其实就是推一下圆的式子 长成这个样子 假设要查询的点是(x, y) 某个圆心是(p, q) \((x - p)^2 + (y - q)^2 \leq p^2 + q^2\) 变成 \( ...
- bzoj2961 共点圆 (CDQ分治, 凸包)
/* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...
- BZOJ2961: 共点圆(CDQ分治+凸包)
题面 传送门 题解 这题解法真是多啊--据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内-- 鉴于圆反演我也不会,这里讲一下直接推的 ...
- [BZOJ2961] 共点圆 [cdq分治+凸包]
题面 BZOJ传送门 思路 首先考虑一个点$(x_0,y_0)$什么时候在一个圆$(x_1,y_1,\sqrt{x_1^2+y_1^2})$内 显然有:$x_1^2+y_1^2\geq (x_0-x_ ...
- BZOJ2961: 共点圆
好久没发了 CDQ分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...
- bzoj2961 共点圆 bzoj 4140
题解: 比较水的一道题 首先我们化简一下式子发现是维护xxo+yyo的最值 显然是用凸包来做 我们可以直接用支持插入删除的凸包 也是nlogn的 因为没有强制在线,我们也可以cdq,考虑前面一半对答案 ...
- [BZOJ2961]共点圆-[凸包+cdq分治]
Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...
- 【BZOJ2961】共点圆(CDQ分治)
[BZOJ2961]共点圆(CDQ分治) 题面 BZOJ 题解 设询问点\((x,y)\),圆心是\((X,Y)\) 那么如果点在园内的话就需要满足 \((X-x)^2+(Y-y)^2\le X^2+ ...
- 【BZOJ4140】共点圆加强版(二进制分组)
[BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ...
- HDU 2157 How many ways??:矩阵快速幂【i到j共经过k个节点的方法数】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2157 题解: 给你一个有向图,n个节点m条边,问你从i到j共经过k个节点的方法数(不算i点). 题解: ...
随机推荐
- circos 绘制关系型图ribbon,并加入透明度
luminance = lum80<<include colors_fonts_patterns.conf>><colors># r,g,b,a color def ...
- http mimetype为multipart/x-mixed-replace报文
http://blog.csdn.net/gmstart/article/details/7064034 服务器推送(Server Push) 推送技术的基础思想是将浏览器主动查询信息改为服务器主动发 ...
- Django入门指南-第7章:模板引擎设置(完结)
http://127.0.0.1:8000/ <!--templates/home.html--> <!DOCTYPE html> <html> <head& ...
- win7 精简板 安装ardunio uno r3驱动
http://www.arduino.cn/thread-2350-1-1.html 下载那个64位的 http://www.keyes-robot.cn/forum.php?mod=viewthre ...
- 程序员面试50题(1)—查找最小的k个元素[算法]
题目:输入n个整数,输出其中最小的k个.例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个数 ...
- Java IO之字符流
public static void main(String[] args) { FileWriter fw = null; try { fw = new FileWriter("/User ...
- Java中JNI的使用详解第一篇:HelloWorld
转自: http://blog.csdn.net/jiangwei0910410003/article/details/17465085 今天开始研究JNI技术,首先还是老套路,输出一个HelloWo ...
- Useful Field of View (UFOV)
IE8不支持canvas,使用excanvas.js,js代码需要放在window.onload=function(){...}内,$(docuemnt).ready(function(){...}) ...
- Android ADB命令基本常用操作
电脑配置好环境变量之后呢,在cmd里面自测一下,是否配置OK: 1.查看目前连接的设备: adb devices 2.使目前连接的设备重启: adb reboot 3.有时候由于设备冲突导致adb出现 ...
- think in java 手记(一)
工作之余,不知道要做些什么.该做的事情都完成的差不多了,想看一下spring的东西,毕竟这些东西用的多.但是又想看一下关于javaee的东西,这个里面的设计模式多.想了一会儿,觉得这些无非都是工具,j ...