BZOJ2961 共点圆[CDQ分治]
题面
其实就是推一下圆的式子
长成这个样子
假设要查询的点是(x, y) 某个圆心是(p, q)
\((x - p)^2 + (y - q)^2 \leq p^2 + q^2\)
变成
\(-\frac{2x}{2y}p + \frac{x^2+y^2}{2y} \leq q\)
那么一个点合法就要对所有圆心都满足上面这个式子
很明显拿斜率截就好啦
然后cdq维护上下凸包
附:cdq维护凸包过程
void cdq(int L, int R){
if(L == R) return ;
int Mid = L + ((R - L) >> 1), tl, tr;
按照时间分左右
cdq(L, Mid);
int t1 = 0, t2 = 0;
for(int i = L; i <= Mid; ++i){
if(node[i].type) continue;
构造上凸包 下凸包
}
for(int i = Mid + 1, j1 = 1, j2 = t2; i <= R; ++i){
if(!node[i].type) continue;
if(node[i].y > 0){//mdf
根据斜率正负判断用上还是下(本题负斜率用下凸包
}
cdq(Mid + 1, R);
归并,按照x排序
}
如果你wa了你要知道
这道题不可以用叉积判凸包
这道题不可以做完减法判slope
这道题不可以不加eps
我哭辽qvq
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#define Sqr(x) ((x)*(x))
using namespace std;
const int N = 5e5 + 5;
const double eps = 1e-11;//这里1e-8到1e-11都可以
struct Node{
int t;
double x, y, k;
bool type, ok;
friend bool operator <(Node x, Node y){return fabs(x.x - y.x) < eps ? x.y < y.y : x.x < y.x;}
}node[N], stk[N], s1[N], s2[N];
int n;
double slope(Node a,Node b)
{
if(fabs(a.x-b.x)<eps)return a.y<b.y?1e18:-1e18;
return (a.y-b.y)/(a.x-b.x);
}
double Dis(Node a,Node b){return sqrt(Sqr(a.x-b.x)+Sqr(a.y-b.y));}//距离和斜率必须这么写!不能减后判断!
//inline double cross(Node x, Node y){return x.x * y.y - x.y * y.x;}
bool rule_t(Node x, Node y){return x.t < y.t;}
bool rule_k(Node x, Node y){return x.k < y.k;}
void cdq(int L, int R){
if(L == R) return ;
int Mid = L + ((R - L) >> 1), tl, tr;
tl = L, tr = Mid + 1;
for(int i = L; i <= R; ++i)
if(node[i].t <= Mid) stk[tl++] = node[i];
else stk[tr++] = node[i];
for(int i = L; i <= R; ++i) node[i] = stk[i];
cdq(L, Mid);
int t1 = 0, t2 = 0;
for(int i = L; i <= Mid; ++i){
if(node[i].type) continue;
while(t1 > 1 && slope(s1[t1 - 1], node[i]) - eps < slope(s1[t1 - 1], s1[t1])) --t1;
s1[++t1] = node[i];//涓嬪嚫鍖咃紙璐熸枩鐜囷級
while(t2 > 1 && slope(s2[t2 - 1], node[i]) + eps > slope(s2[t2 - 1], s2[t2])) --t2;//用叉积判凸包会wa!
s2[++t2] = node[i];//涓婂嚫鍖?
}
for(int i = Mid + 1, j1 = 1, j2 = t2; i <= R; ++i){
if(!node[i].type) continue;
if(node[i].y > 0){//mdf
while(j1 < t1 && slope(s1[j1], s1[j1 + 1]) < node[i].k) ++j1;
if(j1 <= t1 && Dis(s1[j1], s1[0]) < Dis(node[i], s1[j1])) node[i].ok = 0;
// printf("-------\n");s1[j1].print(); node[i].print();
}
else {
while(j2 > 1 && slope(s2[j2], s2[j2 - 1]) > node[i].k) --j2;
if(j2 >= 1 && Dis(s2[j2], s2[0]) < Dis(node[i], s2[j2])) node[i].ok = 0;
// printf("---------\n");s2[j2].print(); node[i].print();
}
}
//printf("%d %d\n", L, R);
cdq(Mid + 1, R);
tl = L, tr = Mid + 1, t1 = L;
while(tl <= Mid && tr <= R)
if(node[tl] < node[tr]) stk[t1++] = node[tl++];
else stk[t1++] = node[tr++];
while(tl <= Mid) stk[t1++] = node[tl++];
while(tr <= R) stk[t1++] = node[tr++];
for(int i = L; i <= R; ++i) node[i] = stk[i];
}
int main() {
scanf("%d", &n);
bool flag = 0;
for(int i = 1; i <= n; ++i){
scanf("%d%lf%lf", &node[i].type, &node[i].x, &node[i].y);
node[i].t = i;
node[i].k = fabs(node[i].y) > eps ? -node[i].x / node[i].y :
(node[i].x > 0 ? -1e18 : 1e18);
if(node[i].type) node[i].ok = flag; else flag = 1;
}
sort(node + 1, node + n + 1, rule_k);
cdq(1, n);
sort(node + 1, node + n + 1, rule_t);
for(int i = 1; i <= n; ++i){
//printf("%d %.4lf %.4lf %d\n", node[i].type, node[i].x, node[i].y, node[i].ok);
if(node[i].type){
if(node[i].ok) printf("Yes\n");
else printf("No\n");
}
}
system("PAUSE");
return 0;
}
BZOJ2961 共点圆[CDQ分治]的更多相关文章
- [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分治, 凸包)
/* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面 然后cdq分治就可以了 代码基本是抄的, */ #inc ...
- BZOJ2961: 共点圆(CDQ分治+凸包)
题面 传送门 题解 这题解法真是多啊--据说可以圆反演转化为动态插入半平面并判断给定点是否在半平面交中,或者化一下改成给定点判断是否所有点都在某一个半平面内-- 鉴于圆反演我也不会,这里讲一下直接推的 ...
- BZOJ2961: 共点圆
好久没发了 CDQ分治,具体做法见XHR的论文… /************************************************************** Problem: 29 ...
- bzoj2961 共点圆 bzoj 4140
题解: 比较水的一道题 首先我们化简一下式子发现是维护xxo+yyo的最值 显然是用凸包来做 我们可以直接用支持插入删除的凸包 也是nlogn的 因为没有强制在线,我们也可以cdq,考虑前面一半对答案 ...
- [BZOJ2961]共点圆-[凸包+cdq分治]
Description 传送门 Solution 考虑对于每一个点: 设圆的坐标为(x,y),点的坐标为(x0,y0).依题意得,当一个点在圆里,需要满足(x-x0)2+(y-y0)2<=x2+ ...
- bzoj 2961 共点圆 cdq+凸包+三分
题目大意 两种操作 1)插入一个过原点的圆 2)询问一个点是否在所有的圆中 分析 在圆中则在半径范围内 设圆心 \(x,y\) 查询点\(x_0,y_0\) 则\(\sqrt{(x-x_0)^2+(y ...
- 【BZOJ2961】共点圆(CDQ分治)
[BZOJ2961]共点圆(CDQ分治) 题面 BZOJ 题解 设询问点\((x,y)\),圆心是\((X,Y)\) 那么如果点在园内的话就需要满足 \((X-x)^2+(Y-y)^2\le X^2+ ...
- 【bzoj2961】 共点圆
http://www.lydsy.com/JudgeOnline/problem.php?id=2961 (题目链接) 题意 按照一定的顺序给出一些圆和一些点,对于每一个点问是否在所有圆内. Solu ...
随机推荐
- vuex状态管理工具
父子组件之间的通信 props传递 父 向子单向传递:且每次 父组件更新时 子组件的props会跟着更新: 如果需要 子组件把数据传递给父组件,就需要在子组件上绑定自定事件 在子组件使用this ...
- c++入门之 再话类
对于类,其结构并不难,但要理解其设计思想也并不容易,在此,我们可以通过下面的代码进一步理解和使用类: # ifndef VECTOR_H_ # define VECTOR_H_ # include & ...
- Could not open connection
意思是不能打开JDBC连接,如果代码没写错的话就是服务没打开,开一下服务就行了,oracle两个必开的服务:OracleServiceORCL和OracleOraDb11g_home2TNSListe ...
- 软件扒网站? 爬虫? F12查看源码? 查看网页源代码?浏览器sources? 区别和联系!
1.软件扒网站: 利用各类扒站网站,如仿站小工具8.0,可以按照规则将网站的未经浏览器简析的前端代码扒下来,并整理成css,js,html等文件夹,很方便.(当然看不到ajax等相关代码) 备注:如果 ...
- Java 数据库操作
目录 Java数据库组织架构 下载驱动包 连接数据库 连接数据库的三个步骤 连接数据库的高开销 Statement接口介绍 PreparedStatement类 使用PreparedStatement ...
- laravel门面和服务提供者使用
关于laravel门面和服务提供者使用的一点见解,门面之词,不足之处,还请多多指教. 在laravel中,我们可能需要用到自己添加的类时,可以建立一个文件夹专门存放类文件,也可以使用laravel ...
- Oracle RMAN备份与还原注意事项
1 备份文件管理 如果要删除之前的备份,不要手动去目录下删除,应该在rman命令模式下使用删除命令,否则虽然在磁盘上把物理备份文件删除了,但是使用备份查看命令会一直看到已经删除的备份文件 list b ...
- [转帖]迎战AMD 7nm 64核EPYC 英特尔至强也玩起了胶水以及性价比
迎战AMD 7nm 64核EPYC 英特尔至强也玩起了胶水以及性价比 Intel 最强CPU 从最开始的双核 到现在的 28核 发展迅猛. https://www.cnbeta.com/article ...
- 逻辑斯特回归tensorflow实现
calss #!/usr/bin/python2.7 #coding:utf-8 from __future__ import print_function import tensorflow as ...
- day 7-6 多线程及开启方式
一. 什么是线程 线程:顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程 ...