bzoj 2961 共点圆 CDQ分治 凸包

来源:互联网 发布:怎么在淘宝商城开店 编辑:程序博客网 时间:2024/05/16 04:47

凸包一向写得蛋疼,何况这题有两个凸包。。。
条件(x1x)2+(y1y)2>x2+y2
化一下可以变成 x12+y122xx12yy1>0
最大化x12+y122xx12yy1 就是最小化b=2xx1+2yy1
y=by1+(x1y1)x
由于不知道y1正负,因此需要维护凹凸两个凸包
CDQ维护一下凸包

#include <bits/stdc++.h>using namespace std;#define N 510000const double inf=1e18,eps=1e-7;int n,h1,h2,r1,r2;int tp[N],q1[N],q2[N],pos[N];double X[N],Y[N],mx,mn,val[N];int cmp1(int x,int y){    if(fabs(X[x]-X[y])<eps)return Y[x]<Y[y];    return X[x]<X[y];}int cmp2(int x,int y){    if(fabs(X[x]-X[y])<eps)return Y[x]>Y[y];    return X[x]<X[y];}int cmp3(int x,int y){return X[x]/Y[x]<X[y]/Y[y];}void solve(int l,int r){    if(l==r)return;    int mid=(l+r)>>1;    solve(l,mid);    for(int i=l;i<=r;i++)pos[i]=i;    h1=h2=1;r1=r2=0;    mx=-inf;mn=inf;    for(int i=l;i<=r;i++)pos[i]=i;    sort(pos+l,pos+mid+1,cmp1);    for(int i=l,t1,t2,t3;i<=mid;i++)if(tp[pos[i]]==0)    {        if(r1>=2)t1=q1[r1-1],t2=q1[r1];t3=pos[i];        while(r1>=2&&(Y[t3]-Y[t2])*(X[t2]-X[t1])+eps>(Y[t2]-Y[t1])*(X[t3]-X[t2]))            r1--,t2=t1,t1=q1[r1-1];        q1[++r1]=t3;        mx=max(mx,X[t3]);mn=min(mn,X[t3]);    }    sort(pos+l,pos+mid+1,cmp2);    for(int i=l,t1,t2,t3;i<=mid;i++)if(tp[pos[i]]==0)    {        if(r2>=2)t1=q2[r2-1],t2=q2[r2];t3=pos[i];        while(r2>=2&&(Y[t3]-Y[t2])*(X[t2]-X[t1])<eps+(Y[t2]-Y[t1])*(X[t3]-X[t2]))            r2--,t2=t1,t1=q2[r2-1];        q2[++r2]=t3;    }    sort(pos+mid+1,pos+r+1,cmp3);    for(int i=mid+1,t,t1,t2;i<=r;i++)if(tp[pos[i]]==1&&r1>=h1)    {        t=pos[i];        if(fabs(Y[t])<eps)        {            val[t]=min(val[t],X[t]*mx);            val[t]=min(val[t],X[t]*mn);        }        else if(Y[t]>0)        {            t1=q2[r2],t2=q2[r2-1];            while(r2>h2&&X[t]*X[t1]+Y[t]*Y[t1]>X[t]*X[t2]+Y[t]*Y[t2])                r2--,t1=t2,t2=q2[r2-1];            val[t]=min(val[t],X[t]*X[q2[r2]]+Y[t]*Y[q2[r2]]);        }        else        {            t1=q1[h1],t2=q1[h1+1];            while(r1>h1&&X[t]*X[t1]+Y[t]*Y[t1]>X[t]*X[t2]+Y[t]*Y[t2])                h1++,t1=t2,t2=q1[h1+1];            val[t]=min(val[t],X[t]*X[q1[h1]]+Y[t]*Y[q1[h1]]);        }    }    solve(mid+1,r);}double dis(int x,int y){    return sqrt((X[x]-X[y])*(X[x]-X[y])+(Y[x]-Y[y])*(Y[x]-Y[y]));}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d%lf%lf",&tp[i],&X[i],&Y[i]),val[i]=inf;    solve(1,n);    for(int i=1;i<=n;i++)        if(tp[i]==1)            puts(X[i]*X[i]+Y[i]*Y[i]-2*val[i]>0||val[i]==inf ? "No":"Yes");    return 0;}
0 0
原创粉丝点击