[BZOJ2961]共点圆-[凸包+cdq分治]
Description
Solution
考虑对于每一个点:
设圆的坐标为(x,y),点的坐标为(x0,y0)。依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+y2。
化简得x02+y02<=2x0*x+2y0*y。
当y0>0,x*(-x0/y0)+0.5y0+x02/(2*y0)<=y,这是一个半平面的式子;当y0<0时同理,但是要变号。
所以对于某个点(x0,y0),我们构造出在它前面所有圆心的凸包。凸包应分为上下。
通过以上式子我们可以得出,当y0>0时应在下凸包上找点(x,y)【该点为直线y=-x0/y0与下凸包的切点,即若此点满足要求,其他任何点都会满足要求。通过这个条件,我们也可以理解把该点理解为2x0*x+2y0*y最小的点】,反之则应该在上凸包上找。
好的让我们假设目前的y0>0,由于凸包上的点(x,y)是按极角排序,x*x0+y*y0是单峰的(这个式子是向量的点乘,其几何意义为:向量a点乘向量b=向量a的长度*向量b的长度*cos(向量a,b的夹角)。所以根据这个定义,证明,就画图吧。qaq正儿八经公式太麻烦了。)上凸包也是一样的。
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const double eps=1e-;
int n;
bool ans[];
struct W{
int tp;double x,y;
friend double operator *(W a,W b){return a.x*b.y-a.y*b.x;}
friend double operator ^(W a,W b){return a.x*b.x+a.y*b.y;}
friend W operator -(W a,W b){return W{,a.x-b.x,a.y-b.y};}
friend bool operator <(W a,W b){return (fabs(a.x-b.x)<eps)?a.y<b.y:a.x<b.x;}
}w[],t[],st[][];//st[0]-上凸包,st[1]-下凸包
double ask(W a,W b){return a.x*b.x+a.y*b.y;}
bool _ok[];
int top0,top1;
bool query(int id)
{
int l,r,mid1,mid2;double minn=1e12;
if (w[id].y<)
{
l=;r=top0;
while (r-l>)
{
mid1=(l*+r)/;mid2=(r*+l)/;
if ((w[id]^st[][mid1])<(w[id]^st[][mid2])) r=mid2;
else l=mid1;
}
for (int i=l;i<=r;i++) minn=min(minn,w[id]^st[][i]); } else
{
l=;r=top1;
while (r-l>)
{
mid1=(l*+r)/;mid2=(r*+l)/;
if ((w[id]^st[][mid1])<(w[id]^st[][mid2])) r=mid2;
else l=mid1;
}
for (int i=l;i<=r;i++) minn=min(minn,w[id]^st[][i]);
}
if (*minn-(w[id].x*w[id].x+w[id].y*w[id].y)<eps) ans[id]=; }
void solve(int l,int r)
{
if (l==r) return;
int mid=(l+r)/,tot=;
solve(l,mid);
solve(mid+,r);
for (int i=l;i<=mid;i++) if (!w[i].tp) t[++tot]=w[i];
sort(t+,t+tot+);
top1=,top0=;
for (int i=;i<=tot;i++)
{
while (top0>&&(st[][top0]-st[][top0-])*(t[i]-st[][top0])>-eps) top0--;
st[][++top0]=t[i];
}
st[][top0+].x=st[][top0].x;st[][top0+].y=-1e12;
for (int i=tot;i;i--)
{
while (top1>&&(st[][top1]-st[][top1-])*(t[i]-st[][top1])>-eps) top1--;
st[][++top1]=t[i];
}
st[][top1+].x=st[][top1].x;st[][top1+].y=1e12;
for (int i=mid+;i<=r;i++) if (w[i].tp&&ans[i]) query(i);
}
bool _is=;
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
{
scanf("%d%lf%lf",&w[i].tp,&w[i].x,&w[i].y);
if (!w[i].tp) _is=;else ans[i]=_is;
}
solve(,n);
for (int i=;i<=n;i++) if (w[i].tp)
if (ans[i]) printf("Yes\n");else printf("No\n");
}
[BZOJ2961]共点圆-[凸包+cdq分治]的更多相关文章
- BZOJ2961: 共点圆(CDQ分治+凸包)
题面 传送门 题解 这题解法真是多啊--据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内-- 鉴于圆反演我也不会,这里讲一下直接推的 ...
- bzoj2961 共点圆 (CDQ分治, 凸包)
/* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...
- 【BZOJ2961】共点圆(CDQ分治)
[BZOJ2961]共点圆(CDQ分治) 题面 BZOJ 题解 设询问点\((x,y)\),圆心是\((X,Y)\) 那么如果点在园内的话就需要满足 \((X-x)^2+(Y-y)^2\le X^2+ ...
- [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分治]
题面 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分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...
- 【bzoj2961】 共点圆
http://www.lydsy.com/JudgeOnline/problem.php?id=2961 (题目链接) 题意 按照一定的顺序给出一些圆和一些点,对于每一个点问是否在所有圆内. Solu ...
- Bzoj2149拆迁队:cdq分治 凸包
国际惯例的题面:我们考虑大力DP.首先重新定义代价为:1e13*选择数量-(总高度+总补偿).这样我们只需要一个long long就能维护.然后重新定义高度为heighti - i,这样我们能选择高度 ...
随机推荐
- BZOJ 2440 完全平方数 莫比乌斯反演模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2440 题目大意: 求第k个无平方因子的数 思路: 二分答案x,求1-x中有多少个平方因 ...
- SGU---462 Electrician 最大生成树
题目链接: https://cn.vjudge.net/problem/SGU-462 题目大意: 有N条电线需要接入电网,第i条电线计划连接ai和bi两个地点,电线有两个属性:ri(电线稳定度)和c ...
- python BaseManager中register()的描述
register(typeid[, callable[, proxytype[, exposed[, method_to_typeid[, create_method]]]]]) A classmet ...
- 把对象缓存到HttpRuntime.Cache里,你能安全地使用它吗?
每每勤勤恳恳,思来想去,趁还有激情,先把它记录下来... 定义一个Stu的类: public class Stu { public string Name { get; set; } public i ...
- 「LGP4719【模板】动态dp」
题目 尽管知道这个东西应该不会考了,但是还是学一学吧 哎要是去年noip之前学该多好 动态\(dp\)就是允许修改的一个\(dp\),比如这道题,我们都知道这是一个树上最大点权独立集 众所周知方程长这 ...
- VC++ UDP网络控制台程序
采用的是VC2008,控制台应用程序,使用UDP编写. 1.服务端代码 //UDPServer.cpp #include <WinSock2.h> #include <stdio. ...
- [转]PowerDesigner使用常见问题锦集
1. 附加:PowerDesigner 的调色板(Palette)快捷工具栏不见了,怎么重新打开,找回来呢 上网搜索了一下”powerdesigner 图形工具栏”,找到了找回PowerDesigne ...
- python执行linux和window的命令
linux: python执行shell脚本常用的方法 import os val=os.system("shell语句") >>> val=os.system ...
- unittest 测试
unittest 测试 单元测试是用来对一个模块.一个函数或者一个类来进行正确性检验的测试工作. 比如对函数abs(),我们可以编写出以下几个测试用例: 输入正数,比如1.1.2.0.99,期待返回值 ...
- Java 数据库操作oracle增删改查,通用封装基于hashmap
pt1:首先安装oracle连接驱动 下载地址:https://pan.baidu.com/s/1jW_ofgU4eJmAn7Y2J5B46A 密码:epkz 1.将ojdbc6.jar导入项目中 ...