http://www.lydsy.com/JudgeOnline/problem.php?id=2961 (题目链接)

题意

  按照一定的顺序给出一些圆和一些点,对于每一个点问是否在所有圆内。

Solution

  我算是明白计算几何题是有多蛋疼了。

  圆包含点$(x_0,y_0)$的条件:$$x*x+y*y>=(x-x_0)*(x-x_0)+(y-y_0)*(y-y_0)$$

$$-2x_0+x_0^2+y_0^2<=2y_0y$$

  题目只说圆心的纵坐标大于$0$,气的我吐出一口老血。所以根据$y_0$的正负,分类讨论,每种情况都是一个半平面,直线的斜率为$-x_0/y_0$,然后我们维护一个上凸包和一个下凸包对询问进行更新,CDQ分治求解就可以了。

细节

  各种细节蛋疼死了,横坐标相等斜率特判,而且是有向线段的斜率两个点的顺序不能乱写。一开始还把斜截式写成了一般式搞了半天我就说怎么不对。

代码

// bzoj2961
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define LD long double
#define inf 1e40
#define eps 1e-10
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=500010;
int n,qu[maxn],st[maxn],ans[maxn];
struct data {LD x,y,k;int op,id;}q[maxn],nq[maxn]; bool cmpk(data a,data b) {return a.k<b.k;}
bool cmpid(data a,data b) {return a.id<b.id;}
LD slope(data a,data b) {
return fabs(a.x-b.x)<=eps ? inf*(a.y<b.y ? 1 : -1) : (b.y-a.y)/(b.x-a.x); //mdzz一定要写a.y<b.y而不是a.y>b.y,有向线段
}
LD dis(int x,int y) {
return (q[x].x-q[y].x)*(q[x].x-q[y].x)+(q[x].y-q[y].y)*(q[x].y-q[y].y);
}
void solve(int l,int r) {
if (l==r) return;
int mid=(l+r)>>1,l1=l,l2=mid+1,top=0,h=1,t=0;
for (int i=l;i<=r;i++) q[i].id<=mid ? nq[l1++]=q[i] : nq[l2++]=q[i];
for (int i=l;i<=r;i++) q[i]=nq[i];
solve(l,mid);
for (int i=l;i<=mid;i++) if (!q[i].op) {
while (top>1 && slope(q[st[top-1]],q[st[top]])<slope(q[st[top]],q[i])+eps) top--;
st[++top]=i;
while (h<t && slope(q[qu[t-1]],q[qu[t]])>slope(q[qu[t]],q[i])-eps) t--;
qu[++t]=i;
}
for (int i=mid+1;i<=r;i++) if (q[i].op) {
if (q[i].y<0) {
while (top>1 && slope(q[st[top-1]],q[st[top]])<q[i].k) top--;
if (top) ans[q[i].id]&=(dis(i,st[top])<=dis(st[top],0)+eps); //判断条件一定要加
}
else {
while (h<t && slope(q[qu[h]],q[qu[h+1]])<q[i].k) h++;
if (h<=t) ans[q[i].id]&=(dis(i,qu[h])<=dis(qu[h],0)+eps); //判断条件一定要加
}
}
solve(mid+1,r);
for (int i=l,j=mid+1,k=l;i<=mid || j<=r;) {
if (j>r || (i<=mid && q[i].x<q[j].x)) nq[k++]=q[i++];
else nq[k++]=q[j++];
}
for (int i=l;i<=r;i++) q[i]=nq[i];
}
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%d%Lf%Lf",&q[i].op,&q[i].x,&q[i].y);
if (q[i].op) q[i].k=-q[i].x/q[i].y;
ans[i]=1;q[i].id=i;
}
sort(q+1,q+1+n,cmpk);
solve(1,n);
sort(q+1,q+1+n,cmpid);
for (int flag=0,i=1;i<=n;i++) {
if (q[i].op) puts(flag && ans[q[i].id] ? "Yes" : "No");
else flag=1;
}
return 0;
}

【bzoj2961】 共点圆的更多相关文章

  1. BZOJ2961: 共点圆

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

  2. BZOJ2961 共点圆[CDQ分治]

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

  3. bzoj2961 共点圆 bzoj 4140

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

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

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

  5. BZOJ2961: 共点圆(CDQ分治+凸包)

    题面 传送门 题解 这题解法真是多啊--据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内-- 鉴于圆反演我也不会,这里讲一下直接推的 ...

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

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

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

  8. 【BZOJ2961】共点圆(CDQ分治)

    [BZOJ2961]共点圆(CDQ分治) 题面 BZOJ 题解 设询问点\((x,y)\),圆心是\((X,Y)\) 那么如果点在园内的话就需要满足 \((X-x)^2+(Y-y)^2\le X^2+ ...

  9. 【BZOJ4140】共点圆加强版(二进制分组)

    [BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ...

随机推荐

  1. Aspose.Cells.dll的用法

    public void OutExcel() { #region WorkbookDesigner designer = new WorkbookDesigner(); Worksheet sheet ...

  2. python 回溯法 子集树模板 系列 —— 4、数字组合问题

    问题 找出从自然数1.2.3.....n中任取r个数的所有组合. 例如,n=5,r=3的所有组合为: 1,2,3 1,2,4 1,2,5 1,3,4 1,3,5 1,4,5 2,3,4 2,3,5 2 ...

  3. 利用Github搭建自己的博客

    教程链接:搭建个人博客 嘿嘿嘿!!一直想自己搭建博客的,一直没机会,这次终于把博客搭了起来.虽然只是一个壳子..套了别人的模板~不过还是很令人兴奋哟!总的来说,就按照这个教程一直往下走,其中有一个坑就 ...

  4. 《Pro SQL Server Internals, 2nd edition》的CHAPTER 2 Tables and Indexes中的Clustered Indexes一节(翻译)

    <Pro SQL Server Internals> 作者: Dmitri Korotkevitch 出版社: Apress出版年: 2016-12-29页数: 804定价: USD 59 ...

  5. 20135202闫佳歆--week6 进程的描述与创建--学习笔记

    此为个人学习笔记存档! week 6 进程的描述与创建 一.进程的描述 1.进程控制块task_struct 以下内容来自视频课件,存档在此. 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述 ...

  6. Linux内核实验作业七

    实验作业:Linux内核如何装载和启动一个可执行程序 20135313吴子怡.北京电子科技学院 [第一部分]理解编译链接的过程和ELF可执行文件格式 1.编译链接的过程 2.ELF可执行文件格式 一个 ...

  7. Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理

    Linux内核设计(第一周)——从汇编语言出发理解计算机工作原理 计算机工作原理 汇编指令 C语言代码汇编分析 by苏正生 原创作品转载请注明出处 <Linux内核分析>MOOC课程htt ...

  8. c# dataGridView 表头格式设置不管用

    解决办法: EnableHeaderVisualStyles设为false

  9. C++:继承访问属性(public/protected/private)

    • 公有继承(public) 公有继承在C++中是最常用的一种继承方式,我们先来看一个示例: #include<iostream> using namespace std; class F ...

  10. 第二个Sprint冲刺第二天(燃尽图)