首页 技术 正文
技术 2022年11月15日
0 收藏 486 点赞 2,501 浏览 2747 个字

题面

传送门

题解

这题解法真是多啊……据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内……

鉴于圆反演我也不会,这里讲一下直接推的好了

如果一个圆的圆心是\((a,b)\),询问点是\((x,y)\),那么这个询问点在圆心上的条件就是

\[\begin{aligned}
(x-a)^2+(y-b)^2\le a^2+b^2 \\
x^2+y^2\le 2ax+2by \\
b\ge -\frac{x}{y}a+\frac{x^2+y^2}{2y}
\end{aligned}
\]

因为题目中已经保证\(y>0\)所以最后一步没有问题

这就是一个半平面交的形式了,问题转化为每次加入圆心点,每次询问是否所有点都在某一个半平面内

这里又有三种做法了,一个是\(O(n\log n)\)的平衡树动态凸包,一个是\(CDQ\)分治,还有一个二进制分组,后面两个都是\(O(n\log^2 n)\)

鉴于我只会中间那个,我们来讲一下\(CDQ\)分治的吧

因为询问都是点在直线上方的形式,我们可以每次对于左边的点跑一个下凸壳,然后维护斜率,对于每一个询问在下凸壳上二分斜率,然后判断那个点是否在直线下方即可

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
double readdb()
{
R double x=0,y=0.1,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(x=ch-'0';(ch=getc())>='0'&&ch<='9';x=x*10+ch-'0');
for(ch=='.'&&(ch=getc());ch>='0'&&ch<='9';x+=(ch-'0')*y,y*=0.1,ch=getc());
return x*f;
}
inline int getop(){R char ch;while((ch=getc())>'9'||ch<'0');return ch-'0';}
const int N=5e5+5;const double eps=1e-10;
inline int sgn(R double x){return x<-eps?-1:x>eps;}
inline double abs(R double x){return x<-eps?-x:x;}
struct node{
double x,y;
double at,bt;
inline node(){}
inline node(R double xx,R double yy):x(xx),y(yy){}
inline node operator +(const node &b)const{return node(x+b.x,y+b.y);}
inline node operator -(const node &b)const{return node(x-b.x,y-b.y);}
inline double operator *(const node &b)const{return x*b.y-y*b.x;}
inline bool operator <(const node &b)const{return x==b.x?y<b.y:x<b.x;}
inline double K(){return y/x;}
}p[N],st[N];double sp[N];int top;
struct qwq{int op;node p;}q[N];
void Graham(int n){
if(n==1)return st[top=1]=p[1],void();
sort(p+1,p+1+n);
st[top=1]=p[1];
fp(i,2,n)if(sgn(p[i].x-st[top].x)){
while(top>1&&sgn((p[i]-st[top-1])*(st[top]-st[top-1]))>=0)--top;
st[++top]=p[i];
}
fp(i,1,top-1)sp[i]=(st[i+1]-st[i]).K();
}
int n;bool ans[N];int sz[N];
void solve(int l,int r){
if(l==r)return;
int mid=(l+r)>>1;
solve(l,mid),solve(mid+1,r);
int tot=0,sz;
fp(i,l,mid)if(!q[i].op)p[++tot]=q[i].p;
fp(i,mid+1,r)if(q[i].op&&ans[i])++sz;
if(!tot||!sz)return;
Graham(tot);
fp(i,mid+1,r)if(q[i].op&&ans[i]){
node &c=q[i].p;double k=-c.x/c.y;
int p=upper_bound(sp+1,sp+top,k)-sp;
ans[i]&=(c.x*c.x+c.y*c.y<=2*(st[p].x*c.x+st[p].y*c.y));
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
fp(i,1,n)q[i].op=getop(),q[i].p.x=readdb(),q[i].p.y=readdb(),sz[i]=sz[i-1]+(!q[i].op),ans[i]=sz[i];
solve(1,n);
fp(i,1,n)if(q[i].op)puts(ans[i]?"Yes":"No");
return 0;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,092
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,568
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,416
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,189
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,825
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,908