BZOJ 2961: 共点圆

突然想起来论文还没刷完QAQ简直智障

2013年xhr论文

卡斜率的时候用点积

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
const int N=500000+5;
const double eps=1e-9;
const double pi=acos(-1.0);
const double inf=1e12;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x<0?-1:1;
}
struct point{
	double x,y;
	bool operator < (const point &p)const{
		return dcmp(x-p.x)?x<p.x:y<p.y;
	}
	void print(){printf("%lf %lf\n",x,y);}
};
point operator - (point a,point b){
	return (point){a.x-b.x,a.y-b.y};
}
point operator + (point a,point b){
	return (point){a.x+b.x,a.y+b.y};
}
double cross(point a,point b){
	return a.x*b.y-a.y*b.x;
}
double cross(point a,point b,point c){
	return cross(b-a,c-a);
}
double dot(point a,point b){
	return a.x*b.x+a.y*b.y;
}
double sqr(double x){return x*x;}
struct Query{
	int k;
	double x,y;
	bool ans;
}q[N];
point p[N],up[N],dw[N];
void cdq(int l,int r){
	if(l==r)return;
	int mid=l+r>>1;
	cdq(l,mid);cdq(mid+1,r);
	int n=0;
	rep(i,l,mid)if(!q[i].k)p[++n]=(point){q[i].x,q[i].y};
	if(!n)return;
	sort(p+1,p+1+n);
	int t1=0,t2=0;
	rep(i,1,n){
		while(t1>=2&&dcmp(cross(up[t1-1],up[t1],p[i]))>=0)t1--;
		up[++t1]=p[i];
	}
	per(i,n,1){
		while(t2>=2&&dcmp(cross(dw[t2-1],dw[t2],p[i]))>=0)t2--;
		dw[++t2]=p[i];
	}
	up[t1+1]=(point){up[t1].x+eps,-inf};
	dw[t2+1]=(point){dw[t2].x-eps,inf};
	rep(i,mid+1,r)if(q[i].k&&q[i].ans){
		point t,tt=(point){q[i].x,q[i].y};
		if(q[i].y<0){
			int x=1,y=t1;
			while(x<=y){
				int mid=x+y>>1;
				if(dcmp(dot(tt,up[mid+1]-up[mid]))>=0)y=mid-1,t=up[mid];
				else x=mid+1;
			}
		}else{
			int x=1,y=t2;
			while(x<=y){
				int mid=x+y>>1;
				if(dcmp(dot(tt,dw[mid]-dw[mid+1]))<=0)y=mid-1,t=dw[mid];
				else x=mid+1;
			}
		}
		q[i].ans&=dcmp(2*tt.x*t.x+2*tt.y*t.y-sqr(tt.x)-sqr(tt.y))>=0;
	}
}
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int n;scanf("%d",&n);
	bool cir=false;
	rep(i,1,n){
		scanf("%d%lf%lf",&q[i].k,&q[i].x,&q[i].y);
		if(q[i].k)q[i].ans=cir;
		else cir=1;
	}
	cdq(1,n);
	rep(i,1,n)if(q[i].k)puts(q[i].ans?"Yes":"No");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值