题面

传送门

题解

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

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

如果一个圆的圆心是\((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;
}

BZOJ2961: 共点圆(CDQ分治+凸包)的更多相关文章

  1. [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_ ...

  2. BZOJ2961 共点圆[CDQ分治]

    题面 bzoj 其实就是推一下圆的式子 长成这个样子 假设要查询的点是(x, y) 某个圆心是(p, q) \((x - p)^2 + (y - q)^2 \leq p^2 + q^2\) 变成 \( ...

  3. bzoj2961 共点圆 (CDQ分治, 凸包)

    /* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...

  4. bzoj2961 共点圆 bzoj 4140

    题解: 比较水的一道题 首先我们化简一下式子发现是维护xxo+yyo的最值 显然是用凸包来做 我们可以直接用支持插入删除的凸包 也是nlogn的 因为没有强制在线,我们也可以cdq,考虑前面一半对答案 ...

  5. Bzoj2149拆迁队:cdq分治 凸包

    国际惯例的题面:我们考虑大力DP.首先重新定义代价为:1e13*选择数量-(总高度+总补偿).这样我们只需要一个long long就能维护.然后重新定义高度为heighti - i,这样我们能选择高度 ...

  6. BZOJ2961: 共点圆

    好久没发了 CDQ分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...

  7. [BZOJ2961]共点圆-[凸包+cdq分治]

    Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...

  8. bzoj 2961 共点圆 cdq+凸包+三分

    题目大意 两种操作 1)插入一个过原点的圆 2)询问一个点是否在所有的圆中 分析 在圆中则在半径范围内 设圆心 \(x,y\) 查询点\(x_0,y_0\) 则\(\sqrt{(x-x_0)^2+(y ...

  9. 【bzoj2961】共点圆 k-d树

    更新:此题我的代码设置eps=1e-8会WA,现在改为1e-9貌似T了 此题网上的大部分做法是cdq分治+凸包,然而我觉得太烦了,于是自己口胡了一个k-d树做法: 加入一个圆$(x,y)$,直接在k- ...

随机推荐

  1. Linux 文件管理命令语法、参数、实例全汇总(一)

    命令:cat   cat 命令用于连接文件并打印到标准输出设备上. 使用权限 所有使用者 语法格式 cat [-AbeEnstTuv] [--help] [--version] fileName 参数 ...

  2. U3D屏幕坐标,世界坐标,像素坐标之间的关系

    U3D中,屏幕坐标和世界坐标单位一样,二者之间是直接的一一对应关系,不受屏幕分辨率影响.默认情况下屏幕空间画布的左下角坐标是世界原点(0,0,0),这种情形下,世界空间的点(1920,1080,任何值 ...

  3. iscroll源码学习(1)

    iscroll是移端端开发的两大利器之一(另一个是fastclick),为了将它整合的avalon,需要对它认真学习一番.下面是我的笔记. 第一天看的是它的工具类util.js //用于做函数节流 v ...

  4. 归纳整理Linux下C语言常用的库函数----内存及字符串控制及操作

    在没有IDE的时候,记住一些常用的库函数的函数名.参数.基本用法及注意事项是很有必要的. 参照Linux_C_HS.chm的目录,我大致将常用的函数分为一下几类: 1. 内存及字符串控制及操作 2. ...

  5. manjaro i3 配置笔记

    更改国内源 sudo pacman-mirrors -GB testing -c China 增加Arch linuxcn源 在/etc/pacman.conf文件末尾添加两行: [archlinux ...

  6. 股票F10

    [股票F10] 股票非行情类的基本面资料统称为股票F10   在各种金融行情终端软件中,用户通过键盘上的F10快捷键,可迅速查看上市公司的非行情信息,诸如:公司概况.财务数据.公司公告.公司新闻.经营 ...

  7. 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

    目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...

  8. mybatis sql语句等日志打印

    加settings <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration ...

  9. static 与 extern 关键字描述说明

    使用static 定义的变量和函数只能用于本模块即为本文件 使用extern 定义的变量和函数可以用于其他模块的引用

  10. 浅析JavaScript访问对象属性和方法及区别

    属性是一个变量,用来表示一个对象的特征,如颜色.大小.重量等:方法是一个函数,用来表示对象的操作,如奔跑.呼吸.跳跃等. 在JavaScript中通常使用”."运算符来存取对象的属性的值.或 ...