题面
题解
设询问点
(x,y)
(
x
,
y
)
,圆心是
(X,Y)
(
X
,
Y
)
那么如果点在园内的话就需要满足
(X−x)2+(Y−y)2≤X2+Y2
(
X
−
x
)
2
+
(
Y
−
y
)
2
≤
X
2
+
Y
2
拆开之后就变成了
x2+y2−2xX≤2yY
x
2
+
y
2
−
2
x
X
≤
2
y
Y
除过去就是
−xyX+x2+y22y≤Y
−
x
y
X
+
x
2
+
y
2
2
y
≤
Y
显然左边是一个直线,那么,这个式子的含义就是,
对于任意
(X,Y)
(
X
,
Y
)
,在
X
X
处的函数值都要小于,
即这个直线在所有的圆心下方。
那么维护一下下凸壳,每次拿斜率去切凸壳,检查一下截距就好了。
当然,上面是假装
y>0
y
>
0
,如果
y<0
y
<
0
的话需要变号,变成了所有圆心都在直线的下方了
这里需要维护一个上凸壳。
用
CDQ
C
D
Q
分治就可以很好的维护这些东西了。
然而我这个傻逼这都不会写
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 500500
#define Sqr(x) ((x)*(x))
const double eps=1e-8;
struct Opt{int op,id;double x,y,k;}p[MAX],tmp[MAX],S1[MAX],S2[MAX];
bool operator<(Opt a,Opt b){return a.k<b.k;}
bool cmp(Opt a,Opt b){return a.id<b.id;}
double Slope(Opt a,Opt b)
{
if(fabs(a.x-b.x)<eps)return a.y<b.y?1e18:-1e18;
return (a.y-b.y)/(a.x-b.x);
}
double Dis(Opt a,Opt b){return sqrt(Sqr(a.x-b.x)+Sqr(a.y-b.y));}
bool ans[MAX];
int n;
void CDQ(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1,t1=l,t2=mid+1,tp1=0,tp2=0;
for(int i=l;i<=r;++i)
if(p[i].id<=mid)tmp[t1++]=p[i];
else tmp[t2++]=p[i];
for(int i=l;i<=r;++i)p[i]=tmp[i];
CDQ(l,mid);
for(int i=l;i<=mid;++i)
{
if(p[i].op)continue;
while(tp1>1&&Slope(S1[tp1-1],p[i])+eps>Slope(S1[tp1-1],S1[tp1]))--tp1;S1[++tp1]=p[i];
while(tp2>1&&Slope(S2[tp2-1],p[i])-eps<Slope(S2[tp2-1],S2[tp2]))--tp2;S2[++tp2]=p[i];
}
t1=tp1,t2=1;
for(int i=mid+1;i<=r;++i)
{
if(!p[i].op)continue;
if(p[i].y<0)
{
while(t1>1&&Slope(S1[t1-1],S1[t1])<p[i].k)--t1;
if(t1>0&&Dis(S1[t1],S1[0])<Dis(S1[t1],p[i]))ans[p[i].id]=false;
}
else
{
while(t2<tp2&&Slope(S2[t2],S2[t2+1])<p[i].k)++t2;
if(t2<=tp2&&Dis(S2[t2],S2[0])<Dis(S2[t2],p[i]))ans[p[i].id]=false;
}
}
CDQ(mid+1,r);
t1=l;t2=mid+1;
for(int i=l;i<=r;++i)
if(t2>r||(t1<=mid&&p[t1].x<p[t2].x))tmp[i]=p[t1++];
else tmp[i]=p[t2++];
for(int i=l;i<=r;++i)p[i]=tmp[i];
}
int main()
{
freopen("2961.in","r",stdin);
freopen("2961.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(int i=1,opt,sum=0;i<=n;++i)
{
double x,y;
cin>>opt>>x>>y;
if(opt==0)p[i]=(Opt){0,i,x,y,0},++sum;
else p[i]=(Opt){1,i,x,y,0};
if(fabs(y)>eps)p[i].k=-x/y;else p[i].k=1e18;
if(opt==1)ans[i]=(bool)sum;
}
sort(&p[1],&p[n+1]);CDQ(1,n);
sort(&p[1],&p[n+1],cmp);
for(int i=1;i<=n;++i)if(p[i].op)puts(ans[i]?"Yes":"No");
return 0;
}