【bzoj2961】 共点圆
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】 共点圆的更多相关文章
- BZOJ2961: 共点圆
好久没发了 CDQ分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...
- BZOJ2961 共点圆[CDQ分治]
题面 bzoj 其实就是推一下圆的式子 长成这个样子 假设要查询的点是(x, y) 某个圆心是(p, q) \((x - p)^2 + (y - q)^2 \leq p^2 + q^2\) 变成 \( ...
- bzoj2961 共点圆 bzoj 4140
题解: 比较水的一道题 首先我们化简一下式子发现是维护xxo+yyo的最值 显然是用凸包来做 我们可以直接用支持插入删除的凸包 也是nlogn的 因为没有强制在线,我们也可以cdq,考虑前面一半对答案 ...
- bzoj2961 共点圆 (CDQ分治, 凸包)
/* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...
- BZOJ2961: 共点圆(CDQ分治+凸包)
题面 传送门 题解 这题解法真是多啊--据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内-- 鉴于圆反演我也不会,这里讲一下直接推的 ...
- [BZOJ2961]共点圆-[凸包+cdq分治]
Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...
- [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分治)
[BZOJ2961]共点圆(CDQ分治) 题面 BZOJ 题解 设询问点\((x,y)\),圆心是\((X,Y)\) 那么如果点在园内的话就需要满足 \((X-x)^2+(Y-y)^2\le X^2+ ...
- 【BZOJ4140】共点圆加强版(二进制分组)
[BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ...
随机推荐
- 十万的License只取决于一个连接
前段时间看到一份代码,小规模.低难度的一个应用,MVC用到极致,业务逻辑却混成一团麻,应该是中了培训班的毒.现在的程序员,大多是没仔细读过<现代操作系统>,没看过编译原理,不知道堆与栈,没 ...
- 20155220 Exp9 Web安全基础实践
Exp9 Web安全基础实践 实验过程 开启webgoat 输入java -jar webgoat-container-7.1-exec.jar,来运行webgoat 在浏览器输入localhost: ...
- Ubuntu 守护进程
项目中用的Qt开发的GUI程序,需要随机自启动. 最初尝试过使用SuperVisor,但是会出现下面的错误. qt.qpa.screen: QXcbConnection: Could not conn ...
- Window下mysql环境配置问题整理
Window下mysql环境配置问题整理 参考如下链接. 无需安装解压版mysql包 创建选项配置 首次启动服务 用mysqld初始化目录 安装后设置和测试 启动服务错误信息 管理员模式打开cmd m ...
- Easy Pipeline,一种轻量级的Python Pipeline库
嗯,很久没有写博客了,最近的工作都是偏开发性质的,以至于没有时间对自己感兴趣的领域进行探索,感觉个人的成长停滞了一些.如何在枯燥的工作中,提取出有助于自己成长的养分,对于每个人来说都是不小的考验. 这 ...
- JQuery快速入门-简介
一.什么是JQuery? jQuery是一个JavaScript库,它通过封装原生的JavaScript函数得到一整套定义好的方法.它的作者是John Resig,于2006年创建的一个开源项目,随着 ...
- C#_委托
委托属于C#中的新名词,它的应用也非常广泛,例如事件就是委托最简单而又直接的例子. 那么首先说说什么是委托,其实委托在用过C或者C++的人看来就是函数指针,不过使用C#的大多数人都没有用过这两门语言, ...
- Java收发邮件过程中具体的功能是怎么实现的
SMTP协议 用户连上邮件服务器后,要想给它发送一封电子邮件,需要遵循一定的通迅规则,SMTP协议就是用于定义这种通讯规则的. 因而,通常我们也把处理用户smtp请求(邮件发送请求)的邮件服务器称之为 ...
- TCP三路握手,本质是一个通信原理相关的问题
在通信系统中,最基本的信息的传递都需要两步,发送方发送的消息和对方的回复确认:A->B Send, B->A Reply(ACK).如果多接触一下其他行业的通信流程和规范,例如航空.铁路调 ...
- B. Lost Array
链接 [http://codeforces.com/contest/1043/problem/B] 题意 自己点开链接看 分析 1到n枚举某个值,判断是否满足并统计 判断方法:假设x序列成立,那么后面 ...