BZOJ2961: 共点圆(CDQ分治+凸包)
题面
题解
这题解法真是多啊……据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内……
鉴于圆反演我也不会,这里讲一下直接推的好了
如果一个圆的圆心是\((a,b)\),询问点是\((x,y)\),那么这个询问点在圆心上的条件就是
(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;
}
BZOJ2961: 共点圆(CDQ分治+凸包)的更多相关文章
- [BZOJ2961] 共点圆 [cdq分治+凸包]
题面 BZOJ传送门 思路 首先考虑一个点$(x_0,y_0)$什么时候在一个圆$(x_1,y_1,\sqrt{x_1^2+y_1^2})$内 显然有:$x_1^2+y_1^2\geq (x_0-x_ ...
- BZOJ2961 共点圆[CDQ分治]
题面 bzoj 其实就是推一下圆的式子 长成这个样子 假设要查询的点是(x, y) 某个圆心是(p, q) \((x - p)^2 + (y - q)^2 \leq p^2 + q^2\) 变成 \( ...
- bzoj2961 共点圆 (CDQ分治, 凸包)
/* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...
- bzoj2961 共点圆 bzoj 4140
题解: 比较水的一道题 首先我们化简一下式子发现是维护xxo+yyo的最值 显然是用凸包来做 我们可以直接用支持插入删除的凸包 也是nlogn的 因为没有强制在线,我们也可以cdq,考虑前面一半对答案 ...
- Bzoj2149拆迁队:cdq分治 凸包
国际惯例的题面:我们考虑大力DP.首先重新定义代价为:1e13*选择数量-(总高度+总补偿).这样我们只需要一个long long就能维护.然后重新定义高度为heighti - i,这样我们能选择高度 ...
- BZOJ2961: 共点圆
好久没发了 CDQ分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...
- [BZOJ2961]共点圆-[凸包+cdq分治]
Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...
- bzoj 2961 共点圆 cdq+凸包+三分
题目大意 两种操作 1)插入一个过原点的圆 2)询问一个点是否在所有的圆中 分析 在圆中则在半径范围内 设圆心 \(x,y\) 查询点\(x_0,y_0\) 则\(\sqrt{(x-x_0)^2+(y ...
- 【bzoj2961】共点圆 k-d树
更新:此题我的代码设置eps=1e-8会WA,现在改为1e-9貌似T了 此题网上的大部分做法是cdq分治+凸包,然而我觉得太烦了,于是自己口胡了一个k-d树做法: 加入一个圆$(x,y)$,直接在k- ...
随机推荐
- Servlet和JSP的本质和区别
基本概念 Servlet Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面.它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTT ...
- 在cmd中显示mysql -uroot-proot 不是命令
这个代码的意思是打开mysql,用户名为root,密码也是root 解决办法:方法一:首先要进入mysql的bin目录下,再执行. 密码错了,重新输入密码,没有密码嘛
- CloudStack 全局参数设置
mem.overprovisioning.factor 内存超分参数 cpu.overprovisioning.factor cpu超分参数
- golang apns升级到http2
记录一下golang中升级apns,使用http2替换http1.1的详细过程. apns使用http2的好处就不用再说了,网上一搜一堆信息.苹果的apns推送在2015年8月就支持了http2协议, ...
- 利率计算--web版--软件工程
1.客户说:帮我开发一个复利计算软件. 完成复利公式计算程序,并成功PUSH到github上. 截止时间:3.10晚12点之前. 按照这个要求完成了. 演示. 计算:本金为100万,利率或者投资回报率 ...
- Java 设计模式系列(五)原型模式
Java 设计模式系列(五)原型模式 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 一.原型模 ...
- 产品设计师 VS UX设计师:你更想成为哪一个?
随着互联网的快速发展,越来越多的应届毕业生也成为设计师的一员.他们当中的许多人选择UX设计师作为第一份工作,也有一些人选择做一个产品设计师.你是否也想成为设计师呢?这两种设计师你更倾向于哪一个呢?在你 ...
- spring 启动完成后事件监听器处理
有时候我们在spring容器启动完成后,我们需要做一些处理动作,这个时候怎么做呢? spring提供了事件监听器的处理机制. spring提供了内置的几类的事件: ContextClosedEvent ...
- UVa 12093 Protecting Zonk (树形DP)
题意:给定一个有n个节点的无根树,有两种装置A和B,每种都有无限多个.在某个节点X使用A装置需要C1的花费,并且此时与节点X相连的边都被覆盖.在某个节点X使用B装置需要C2的花费,并且此时与节点X相连 ...
- Redis是可以安装成windows服务-开机自启 win7 64位
其实Redis是可以安装成windows服务的,开机自启动,命令如下: redis-server --service-install redis.windows.conf 安装完之后,就可看到Redi ...