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. 20155217《网络对抗》Exp06 信息搜集与漏洞扫描

    20155217<网络对抗>Exp06 信息搜集与漏洞扫描 实践内容 各种搜索技巧的应用 DNS IP注册信息的查询 基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具体服务的查点 ...

  2. # 20155218 徐志瀚 EXP7 网络欺诈

    20155218 徐志瀚 EXP7 网络欺诈 1. URL攻击 1.在终端中输入命令netstat -tupln |grep 80,查看80端口是否被占用 发现没有被占用: 2.输入指令service ...

  3. Hibernate一对多关联关系保存时的探究

    在以前使用hibernate时,经常对保存存在关联关系的对象时,不确定是否能保存成功.    因此,特意对一对多关系的2个对象进行实践. 一.pojo类和配置文件的准备         这里有一点提前 ...

  4. [2016北京集训测试赛17]crash的游戏-[组合数+斯特林数+拉格朗日插值]

    Description Solution 核心思想是把组合数当成一个奇怪的多项式,然后拉格朗日插值..:哦对了,还要用到第二类斯特林数(就是把若干个球放到若干个盒子)的一个公式: $x^{n}=\su ...

  5. linux之 sed 基础

    转载:https://www.cnblogs.com/chensiqiqi/p/6382080.html sed 介绍 Sed命令是操作,过滤和转换文本内容的强大工具.常用功能有增删改查(增加,删除, ...

  6. GitLab篇之Linux下环境搭建

    之前公司一直在使用微软的VSS和SVN做为源代码管理工具,考虑到VSS和SVN的局限性,个人一直建议我们应该采用Git来管理我们的源代码.Git的好处不多说相信大家也都知道的.Git不仅仅是一个源代码 ...

  7. 华为云Istio服务网格,让应用治理智能化、可视化

  8. [文章存档]Azure上部署的java app在向第三方服务传送中文时出现乱码

    https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-java ...

  9. 软件工程 BUAAMOOC项目Postmortem结果

    设想和目标 1.我们的软件要解决什么问题?是否定义的很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件是基于北航MOOC网站做的Android手机客户端,用于便捷的在学校里通过手机做到随时随地 ...

  10. java计算器实验报告

    一.实验目的 1.熟悉java图形用户界面的设计原理和程序结构 2.能设计复核问题要求的图形用户界面程序 3.熟悉java awt和swing的组合 4.掌握常用组建的事件借口 5.会应用awt和sw ...