【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;
}
时间: 2024-08-05 11:58:54

【bzoj2961】 共点圆的相关文章

[bzoj2961] 共点圆

Description 在平面直角坐标系中,Wayne需要你完成n次操作,操作只有两种: 1.0 x y.表示在坐标系中加入一个以(x, y)为圆心且过原点的圆. 2.1 x y.表示询问点(x, y)是否在所有已加入的圆的内部(含圆周),且至少在一个圆内部(含圆周). 为了减少你的工作量,题目保证圆心严格在x轴上方(纵坐标为正),且横坐标非零. Input 第1行一个整数n. 接下来n行,每行第一个数是0或1,分别表示两种操作. 接着有两个实数x和y,具体意义见题面. Output 对于每个询

BZOJ 2961 共点圆 CDQ分治+凸包

题目大意:给定平面,多次插入点和圆,每次插入点时询问当前插入的点是否在之前插入的所有圆中并且至少在一个圆中 直接用数据结构维护这些点和圆不是很好写,我们考虑CDQ分治 对于每层分治,我们需要对于[mid+1,r]中的每个点求出[l,mid]中是否所有的圆都覆盖了这个点 设点的坐标为(x0,y0),那么这个点在所有圆内必须满足对于所有的圆心(x,y),(x-x0)^2+(y-y0)^2<=x^2+y^2,即2*x*x0+2*y*y0>=x0^2+y0^2 我们发现上面的式子是一个半平面,斜率为-

总结与心得(持续更新)

不知道为什么,刚学的算法过了2个月就忘得一干二净,我并没有背代码啊,当时学的时候还刷了好多题来着→_→,我是不是大脑能力严重衰退了. 动态规划 单调队列 一般情况下,${dp}$方程可以搞成这样:${f_i=f_j+t_j+t_i}$,只要其中没有变量同时与${i,j}$都有关,那么我们可以用单调队列来做,单调队列里面元素的关键字就是与${j}$有关的东西${f_j+t_j}$.example:生产产品 有些比较特殊的,虽然存在同时与${i,j}$相关的函数,但是这个函数比较简单,使得已经存在在

分治笔记

分治 一.简单介绍 二.集中题目 1.  动态最小生成树(了解) 2.  CDQ分治 (1)       蝗虫(运用) (2)       CASH(了解) (3)       共点圆(了解) 3.  树分治 (1)       树链剖分(运用)  例题::BZOJ2243 每个点记录siz.son.fa.top.dfn (siz:该点子树大小.son:该点重链上的儿子(就是重儿子),top:该点重链的顶端,如果不在重链上则top=本身) 先dfs一遍,求出siz,son,fa 再dfs一遍(依

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

Spring mvc 中使用ftl引用共通文件出错 FreeMarker template error: Error reading included file &quot;/WEB-INF/ftl/common/errormessage.ftl&quot;

初次接触spring mvc,想做一个小的练习项目,结果在ftl文件中引用其它的共通ftl文件时出错. 目录结构如图所示,想在login.ftl中引用common下的errormessage.ftl <#include '/WEB-INF/ftl/common/errormessage.ftl' /> 结果画面报错: FreeMarker template error: Error reading included file "/WEB-INF/ftl/common/errormes

一球从M米高度自由下落,每次落地后返回原高度的一半,再落下。 它在第N次落地时反弹多高?共经过多少米? 保留两位小数

题目描述 输入 M N 输出 它在第N次落地时反弹多高?共经过多少米? 保留两位小数,空格隔开,放在一行 样例输入 1000 5 样例输出 31.25 2875.00 代码:#include<stdio.h>int main(){    double M,sum=0;    int N,i;    scanf("%lf%d",&M,&N);    sum=M;    for(i=2;i<=N;i++)    {                 M=M/

材料管理框架:一个共通的viewModel搞定所有的分页查询

前言 大家看标题就明白了我想写什么了,在做企业信息化系统中可能大家写的最多的一种页面就是查询页面了.其实每个查询页面,除了条件不太一样,数据不太一样,其它的其实都差不多.所以我就想提取一些共通的东西出来,再写查询时只要引入我共通的东西,再加上极少的代码就能完成.我个人比较崇尚代码简洁干净,有不合理的地方欢迎大家指出. 这篇文章主要介绍两个重点:1.前台viewModel的实现.2.后台服务端如何简洁的处理查询请求. 需求分析 查询页面要有哪些功能呢 1.有条件部输入查询条件(这个不打算做成共通的

资本与互联网共舞下的体育产业如何向前发展?

7月11日,2016年欧洲杯以葡萄牙1—0战胜法国夺冠落下帷幕.而在这期间,中国的球迷也是在熬夜看球,也许还沉浸在欧洲杯的激动心情中.根据欧足联公布的数据显示,欧洲杯开赛的5天内,在中国大陆的央视直播欧洲杯赛,其平均收视率就达到1.49%,也就意味着有3500多万精准人群在固定收看比赛.除了电视媒体这一块,还有新媒体下的视频直播平台.脱口秀等网络节目对欧洲杯推出多元化节目也获得很高的点击量.而足球的热潮还没有褪去,我们就要在八月迎来奥运会,这一重大的体育赛事又将为中国的年轻体育迷们带来一场场激动