传送门:bzoj2961
我很绝望,bzoj WA \text{WA} WA了两页了还是没过,调了两天!
单独把询问点 y = 0 y=0 y=0的情况提出来算了发现网上好多题解的代码都判 WA \text{WA} WA了,然而除了询问点 y = 0 y=0 y=0的情况都没对拍出错来TAT。
我真傻,真的,斜率 k k k设成 int \text{int} int都没发现。
&判上/下凸壳一定要用斜率比,而不是叉积…
假设查询点坐标为 ( x , y ) (x,y) (x,y),每个圆心坐标分别为 ( x i , y i ) (x_i,y_i) (xi,yi),当前点在所有圆内需满足:
x i 2 + y i 2 ≥ ( x i − x ) 2 + ( y i − y ) 2 x_i^2+y_i^2\geq (x_i-x)^2+(y_i-y)^2 xi2+yi2≥(xi−x)2+(yi−y)2
转化一下:
2 y y i ≥ − 2 x x i + x 2 + y 2 2yy_i\geq -2xx_i+x^2+y^2 2yyi≥−2xxi+x2+y2
当 y > 0 y>0 y>0时:
y i ≥ − x y x i + x 2 + y 2 2 y y_i\geq -\dfrac{x}{y}x_i+\dfrac{x^2+y^2}{2y} yi≥−yxxi+2yx2+y2
也就是所有点都在 y = − x y x + x 2 + y 2 2 y y=-\dfrac{x}{y}x+\dfrac{x^2+y^2}{2y} y=−yxx+2yx2+y2之上。
当 y < 0 y<0 y<0时:
y i ≤ − x y x i + x 2 + y 2 2 y y_i\leq -\dfrac{x}{y}x_i+\dfrac{x^2+y^2}{2y} yi≤−yxxi+2yx2+y2
也就是所有点都在 y = − x y x + x 2 + y 2 2 y y=-\dfrac{x}{y}x+\dfrac{x^2+y^2}{2y} y=−yxx+2yx2+y2之下。
y = 0 y=0 y=0的情况单独提出来直接维护即可。
于是可以对所有圆心坐标分别维护上凸壳和下凸壳, y > 0 y>0 y>0和 y < 0 y<0 y<0时分别在下凸壳和上凸壳上找到对应的切点计算即可。
于是可以 c d q cdq cdq分治,使得点坐标和询问直线斜率有序化,构造左边部分的上下凸壳,拿右边询问扫一遍即可。
在线的(bzoj4140共点圆加强版)可以二进制分组维护。
WA
#include
#define prit(x) cerr<<#x<<":"<
using namespace std;
const int N=5e5+10;
typedef long double db;
const db eps=1e-8;
int n,m,stk[N],top;
bool pr[N],ans[N],exi;db l,r;
struct P{
db x,y;
P(db x_=0.0,db y_=0.0):x(x_),y(y_){};
P operator +(const P&ky){return P(x+ky.x,y+ky.y);}
P operator -(const P&ky){return P(x-ky.x,y-ky.y);}
db operator ^(const P&ky){return x*ky.y-y*ky.x;}
P operator *(const db&ky){return P(x*ky,y*ky);}
P operator /(const db&ky){return P(x/ky,y/ky);}
}a[N],b[N],ori;
int dcmp(db x){if(fabs(x)<eps) return 0;return x>0?1:-1;}
struct Q{
int typ,id,dr;db k;P p;
bool operator <(const Q&ky)const{
if(typ^ky.typ) return typ<ky.typ;
return typ?k<ky.k:p.x<ky.p.x;
}
}q[N],p[N];
db slope(P a,P b)
{
if(!dcmp(a.x-b.x)) return a.y<b.y?1e18:-1e18;
return (a.y-b.y)/(a.x-b.x);
}
db dis(P a,P b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
bool uvalid(P a,P b)
{
return dis(b,ori)<dis(a,b);
//return 2*a.p.x*b.x+2*a.p.y*b.y
}
void sol(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1,i=l,j=mid+1,k,pos,ta,tb,qa,qb;
for(k=l;k<=r;++k)
if(q[k].dr>mid) p[j++]=q[k];
else p[i++]=q[k];
for(k=l;k<=r;++k) q[k]=p[k];
for(pos=mid+1;pos<=r && (!q[pos].typ);++pos);
if((!q[l].typ)&&pos<=r){
ta=tb=0;
for(i=l;i<=mid && (!q[i].typ);++i){
for(;ta>1 && slope(a[ta-1],q[i].p)-eps<slope(a[ta-1],a[ta]);--ta);a[++ta]=q[i].p;
for(;tb>1 && slope(b[tb-1],q[i].p)+eps>slope(b[tb-1],b[tb]);--tb);b[++tb]=q[i].p;
}
qa=1;qb=tb;
for(i=pos;i<=r;++i)
if(q[i].p.y<0){
for(;qb>1 && slope(b[qb-1],b[qb])<q[i].k;--qb);
if(qb>0 && ans[q[i].id] && uvalid(q[i].p,b[qb])) ans[q[i].id]=false;
}else{
for(;qa<ta && slope(a[qa],a[qa+1])<q[i].k;++qa);
if(qa<=ta && ans[q[i].id] && uvalid(q[i].p,a[qa])) ans[q[i].id]=false;
}
}
sol(l,mid);sol(mid+1,r);
}
int main(){
// freopen("ty.txt","r",stdin);
int i;double x,y;db ql,qr;
scanf("%d",&n);
for(i=1;i<=n;++i){
scanf("%d%lf%lf",&q[++m].typ,&x,&y);
q[m].p=P(x,y);
if(q[m].typ){
pr[i]=ans[i]=true;
if(!exi) {ans[i]=false;m--;continue;}
if(fabs(y)<eps){
if(x<l || x>r)
ans[i]=false;
m--;continue;
}
q[m].k=-x/y;
// q[m].k=(fabs(y)
}else{
ql=0,qr=x+x;if(ql>qr) swap(ql,qr);
if(!exi) l=ql,r=qr;else l=max(l,ql),r=min(r,qr);
exi=true;
}
q[m].id=i;q[m].dr=m;
}
sort(q+1,q+m+1);sol(1,m);
for(i=1;i<=n;++i) if(pr[i]) puts(ans[i]?"Yes":"No");
return 0;
}
/*
9
0 2 3
0 4 1
1 1 1
0 -3 2
1 0 0
1 2 0
1 3 0
1 0 1
1 1 1
*/