2961: 共点圆
根据圆方程 ( x − x 0 ) 2 + ( y − y 0 ) 2 ≤ ( x 0 2 + y 0 2 ) 2 (x-x_0)^2+(y-y_0)^2 \le (x_0^2+y_0^2)^2 (x−x0)2+(y−y0)2≤(x02+y02)2
解得 x 0 2 + y 0 2 ≤ 2 x x 0 + 2 y y 0 x_0^2+y_0^2\le 2xx_0+2yy_0 x02+y02≤2xx0+2yy0
右边项可以看成 ( 2 x , x 0 ) ⋅ ( 2 y , y 0 ) (2x,x_0)·(2y,y_0) (2x,x0)⋅(2y,y0)
所以我们二进制分组+凸包就可以了。
CDQ分治也可以。
#include<stack>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=5e5+5;
const double EXP=1e-8;
int n,q,Top,LstAns,S[MAXN],Len[MAXN],tot;
struct Point{
double x,y;
bool operator <(const Point b)const{return x==b.x?y<b.y:x<b.x;}
double operator ^(const Point b)const{return x*b.y-y*b.x;}
double operator *(const Point b)const{return x*b.x+y*b.y;}
Point operator -(const Point b)const{return (Point){x-b.x,y-b.y};}
}Stk[MAXN],a[MAXN];
vector<Point> TB[32];
void Make_TB(int p,int L,int R){
TB[p].clear();Top=0;sort(a+L,a+R+1);
for(int i=L;i<=R;i++){
while(Top>1&&((a[i]-Stk[Top])^(Stk[Top]-Stk[Top-1]))>=0) Top--;
Stk[++Top]=a[i];
}
for(int i=1;i<=Top;i++) TB[p].push_back(Stk[i]);
}
void Insert(Point x){
a[++n]=x;for(int mi=1;mi==Len[tot]&&tot;mi*=2) tot--;++tot;
S[tot]=S[tot-1]+Len[tot-1];Len[tot]=n-S[tot];
Make_TB(tot,S[tot]+1,S[tot]+Len[tot]);
}
double Find(int p,int L,int R,Point x){
double ret=1e9;
while(L<=R){
if(R-L<=3) break;
int mid1=L+(R-L)/3,mid2=R-(R-L)/3;
if(TB[p][mid1]*x>TB[p][mid2]*x) L=mid1;else R=mid2;
}
for(int i=L;i<=R;i++) ret=min(ret,TB[p][i]*x);
return ret;
}
double _abs(double x){return x<0?-x:x;}
//bool cmp(double x){if(_abs(x)<=EXP||x<=0) return 1;else return 0;}
void Query(Point x){
double Ans=1e9;
for(int i=1;i<=tot;i++) Ans=min(Ans,Find(i,0,TB[i].size()-1,x));
if(Ans>=x.x*x.x+x.y*x.y&&tot>0) LstAns++,puts("Yes");else puts("No");
}
int main(){
// freopen("4140.in","r",stdin);
// freopen("4140.out","w",stdout);
scanf("%d",&q);
for(int i=1;i<=q;i++){
int Type;double x,y;scanf("%d%lf%lf",&Type,&x,&y);x+=LstAns,y+=LstAns;
if(Type) Query((Point){x,y});else Insert((Point){x*2,y*2});
}
return 0;
}

本文详细解析了共点圆的数学问题,通过将圆方程转换为不等式,运用二进制分组和凸包算法进行求解,介绍了CDQ分治策略,并提供了具体的C++实现代码,展示了如何处理大量圆的共点判断。
393

被折叠的 条评论
为什么被折叠?



