用了Lambda表达式,需要开C++11,只能在darkbzoj上交。
由于所有圆都过原点,直接反演后将所有圆交的区域表示为半平面交,然后上CDQ分治判断就行了。
代码:
#include
#define ll long long
#define re register
#define db double
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T num=c^48;
while(isdigit(c=gc()))num=((num+(num<<2))<<1)+(c^48);return f?-num:num;
}inline int gi(){
return get_integer<int>();}
template<typename T>T get_float(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=(x*10)+(c^48);if(c!='.')return f?-x:x;
db y=1.;while(isdigit(c=gc()))x+=(y/=10)*(c^48);return f?-x:x;
}inline db gd(){
return get_float<db>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs db eps=1e-8,R=1e4;
inline db sqr(db x){
return x*x;}
inline int sign(db x){
return x<-eps?-1:(x>eps?1:0);}
struct Pnt{
db x,y;Pnt(){
}Pnt(db _x,db _y):x(_x),y(_y){
}
friend Pnt operator+(cs Pnt &a,cs Pnt &b){
return Pnt(a.x+b.x,a.y+b.y);}
friend Pnt operator-(cs Pnt &a,cs Pnt &b){
return Pnt(a.x-b.x,a.y-b.y);}
friend Pnt operator*(cs Pnt &a,db b){
return Pnt(a.x*b,a.y*b);}
friend Pnt operator/(cs Pnt &a,db b){
return Pnt(a.x/b,a.y/b);}
friend db operator*(cs Pnt &a,cs Pnt &b){
return a.x*b.y-a.y*b.x;}
friend db dot(cs Pnt &a,cs Pnt &b){
return a.x*b.x+a.y*b.y;}
inline db len()cs{
return sqrt(x*x+y*y);}
inline db ang()cs{
return atan2(y,x);}
inline Pnt rot()cs{
return Pnt(y,-x);}
};
inline db crs(cs Pnt &a,cs Pnt &b,cs Pnt &c){
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
struct Line{
Pnt s,t;Line(){
}Line(cs Pnt &_s,cs Pnt &_t):s(_s),t(_t){
}
Pnt dir()cs{
return t-s;}
};
inline Pnt inter(cs Line &a,cs Line &b){
return a.s+(a.dir())*(crs(b.s,b.t,a.s)/((a.dir())*(b.dir())));
}
inline Line inv(cs Pnt &O){
Pnt s=O*sqr(R/O.len());return Line(s,s+O.rot());
}
inline Pnt Inv(cs Pnt &O){
return O*sqr(R/O.len());}
cs int N=5e5+7;
int n;int typ[N];
Pnt p[N];bool ans[N];
void solve(int l,int r,std::vector<Line> &S,std::vector<int> &P){
if(l==r){
if(typ[l]==0)S.push_back(inv(p[l]*2));
else if(ans[l])p[l]=Inv(p[l]),P.push_back(l);return;
}int mid=(l+r)>>1;
std::vector<Line> sl,sr;std::vector<int> pl,pr;
solve(l,mid,sl,pl),solve(mid+1,r,sr,pr);
if(sl.size()){
unsigned int h=0;
for(int re i:pr){
while(h+1<sl.size()&&p[i].x>=inter(sl[h],sl[h+1]).x)++h;
ans[i]&=sign(crs(sl[h].s,sl[h].t,p[i]))>=0;
}
}
auto cmp_Line=[](cs Line &a,cs Line &b)->bool{
return sign(a.dir()*b.dir())?sign(a.dir()*b.dir())>0:sign(crs(b.s,b.t,a.t))<0;
};
auto judge=[](cs Pnt &a,cs Line &b)->bool{
return sign(b.dir()*(a-b.s))>=0;};
auto ins=[&](cs Line &it)->void{
while(S.size()>1&&judge(inter(S[S.size()-2],it),S.back()))S.pop_back();
while(S.size()&&!sign(it.dir()*S.back().dir()))S.pop_back();
S.push_back(it);
};unsigned int hl=0,hr=0;
while(hl<sl.size()&&hr<sr.size())ins(cmp_Line(sl[hl],sr[hr])?sl[hl++]:sr[hr++]);
while(hl<sl.size())ins(sl[hl++]);while(hr<sr.size())ins(sr[hr++]);
auto cmp_x=[](int i,int j)->bool{
return p[i].x<p[j].x;};
auto push=[&](int i)->void{
if(ans[i])P.push_back(i);};hl=hr=0;
while(hl<pl.size()&&hr<pr.size())push(cmp_x(pl[hl],pr[hr])?pl[hl++]:pr[hr++]);
while(hl<pl.size())push(pl[hl++]);while(hr<pr.size())push(pr[hr++]);
}
void Main(){
n=gi();bool exi=false;
for(int re i=1;i<=n;++i){
typ[i]=gi();p[i].x=gd(),p[i].y=gd();
ans[i]=exi;if(typ[i]==0)exi=true;
}std::vector<Line> S;std::vector<int> P;solve(1,n,S,P);
for(int re i=1;i<=n;++i)if(typ[i]==1)puts(ans[i]?"Yes":"No");
}
inline void file(){
#ifdef zxyoi
freopen("cir.in","r",stdin);
freopen("cir.out","w",stdout);
#endif
}
signed main(){
file();Main();return 0;}