【BZOJ2961】共点圆(圆的反演)(半平面交)(CDQ分治)

传送门


用了Lambda表达式,需要开C++11,只能在darkbzoj上交。

题解:

由于所有圆都过原点,直接反演后将所有圆交的区域表示为半平面交,然后上CDQ分治判断就行了。


代码:

#include<bits/stdc++.h>
#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;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值