【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点). 题解: ...
随机推荐
- 2018.09.21 codeforces1051D. Bicolorings(线性dp)
传送门 sb线性DP. f[i][j][0/1/2/3]f[i][j][0/1/2/3]f[i][j][0/1/2/3]表示前i列j个连通块且第i列状态为00/01/10/11时的方案总数. 这个显然 ...
- hdu-1163(九余数定理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1163 思路: 九余数定理:一个数对九取余的结果叫做九余数, 一个数的各个位数相加的得到的小于10的数也 ...
- 带你快速进入.net core的世界(转)
出处:http://www.cnblogs.com/zhaopei/p/netcore.html 阅读目录 vmware虚拟机安装 CentOS7.3安装 Windows的客户端软件 .NET Cor ...
- Python网络编程总结
----learn from luffycity---- 1. 什么是C/S架构? C指的是client(客户端软件),S指的是Server(服务端软件),C/S架构就是基于网络实现客户端与服务端通信 ...
- UVa 11491 Erasing and Winning (贪心,单调队列或暴力)
题意:给一个数字(开头非0),拿掉其中的d个数字,使剩下的数字最大(前后顺序不能变). 析:拿掉d个数字,还剩下n-d个数字.相当于从n个数字中按先后顺序选出n-d个数字使组成的数字最大,当然采用窗口 ...
- java程序设计基本概念 jvm
JVM (1)对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中.对于equals相等的字符串 ...
- NoSQL: Cassandra, HBase, RocksDB
转自: http://www.linkedin.com/pulse/nosql-cassandra-hbase-rocksdb-siddharth-anand I've had the pleasur ...
- java web 项目启动的根目录,以及项目启动后使用的端口具体是哪一个
1.今天启动项目发现一直找不到网页,原来是自己浏览器地址的根目录出现了问题,那么系统中的根目录(也就是项目名)到底是哪个,究竟以哪个为基准? 这里有一地方不能忽视:见图片 在普通的java web项目 ...
- Chrome For EBS
https://chrome.google.com/webstore/detail/oracle-ebs-r12-enablement/ekkagabmggbmpmncofhgkfigmeldifnc ...
- 【TypeScript】TypeScript 学习 4——模块
前端数据验证在改善用户体验上有很大作用,在学了之前的知识的时候,我们很可能会写出以下代码: interface StringValidator { isAcceptable(s: string): b ...