这题真是写的我有点绝望。菜不禁声。其实一开始是想拿KD tree树写的,听说能过,但是wa成狗??至今改不对gg。一个点(x0,y0)在圆(x,y)内,要求
(x−x0)2+(y−y0)2<=x2+y2
化简一下就是
x20+y20<=2x0x+2y0y
假设
y0>0
,我们有
y>=−x0y0∗x+x20+y202y0
,是一个半平面!
也就是说我们现在把问题转化为:对于每一个询问,相当于给定了一个半平面,问你是否所有点都在这个半平面上。
这个东西我们可以维护一个凸包(因为y0正负未定,所以要维护上下两个凸包),每次拿着半平面的斜率去在凸包上二分,找到那个卡到的点,只需判定这个点在不在半平面上即可。如果y0>0,去下凸包上找,否则去上凸包上找。至于为什么…我只能形象的理解一下,就是y0>0时,我们的半平面是在一条直线的上方,我们找到下凸包对于这条直线而言最下面的那个点,只要他都在直线上方,那么剩下的点也一定都在直线上方。然后我们可以cdq分治,利用特殊的技巧来维护。(先都按斜率从小到大排序,然后每次分治时按标号分两部分,先递归处理[l,mid],然后为了方便线性处理凸包,我们每次分治完按x坐标排好序。我们处理好[l,mid]后,做出[l,mid]中的凸包,然后因为此时[mid+1,r]还是按斜率从小到大排好序的,我们可以线性的扫一遍更新答案。然后再去递归处理[mid+1,r])。复杂度
O(nlogn)
还有一些理解可以见2013集训队论文xhr神犇的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 1e40
#define N 500010
#define eps 1e-10
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,tot=0,q1[N],q2[N];//q1,下凸包,q2,上凸包
bool ans[N],one=0;
struct point{
double x,y;
};
struct event{
point x;int op,id,qid;double k;
}e[N],tmp[N];
inline bool cmp(event a,event b){return a.k<b.k;}
inline double abs(double x){return x<0?-x:x;}
inline double sqr(double x){return x*x;}
inline double slope(point a,point b){
if(abs(b.x-a.x)<eps) return inf;
return (b.y-a.y)/(b.x-a.x);
}
inline double dis(point a,point b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
inline double R(point a){return sqr(a.x)+sqr(a.y);}
inline void cdq(int l,int r){
if(l==r) return;
int mid=l+r>>1,p1=l,p2=mid+1,h1=1,h2=1,t1=0,t2=0;
for(int i=l;i<=r;++i)
if(e[i].id<=mid) tmp[p1++]=e[i];
else tmp[p2++]=e[i];
memcpy(e+l,tmp+l,sizeof(e[0])*(r-l+1));
cdq(l,mid);
for(int i=l;i<=mid;++i){
if(e[i].op) continue;
while(h1<t1&&slope(e[q1[t1]].x,e[i].x)<slope(e[q1[t1-1]].x,e[q1[t1]].x)+eps) --t1;
q1[++t1]=i;
while(h2<t2&&slope(e[q2[t2]].x,e[i].x)+eps>slope(e[q2[t2-1]].x,e[q2[t2]].x)) --t2;
q2[++t2]=i;
}for(int i=mid+1;i<=r;++i){
if(!e[i].op) continue;
if(e[i].x.y>0){
while(h1<t1&&slope(e[q1[h1]].x,e[q1[h1+1]].x)<e[i].k) ++h1;
if(h1<=t1&&dis(e[q1[h1]].x,e[i].x)>R(e[q1[h1]].x)) ans[e[i].qid]=0;
}else{
while(h2<t2&&slope(e[q2[t2-1]].x,e[q2[t2]].x)<e[i].k) --t2;
if(h2<=t2&&dis(e[q2[t2]].x,e[i].x)>R(e[q2[t2]].x)) ans[e[i].qid]=0;
}
}cdq(mid+1,r);p1=l;p2=mid+1;
for(int i=l;i<=r;++i)
if(p2>r||p1<=mid&&e[p1].x.x<e[p2].x.x) tmp[i]=e[p1++];else tmp[i]=e[p2++];
memcpy(e+l,tmp+l,sizeof(e[0])*(r-l+1));
}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;++i){
e[i].op=read();scanf("%lf%lf",&e[i].x.x,&e[i].x.y);e[i].id=i;
if(e[i].op){
e[i].qid=++tot;if(one) ans[tot]=1;
if(e[i].x.y) e[i].k=-e[i].x.x/e[i].x.y;else e[i].k=inf;
}else one=1;
}sort(e+1,e+n+1,cmp);cdq(1,n);
for(int i=1;i<=tot;++i) puts(ans[i]?"Yes":"No");
return 0;
}