bzoj 2961
根据“点在圆内”关系,列出点P(x0,y0)在圆C(x,y)内的关系:
(x-x0)^2+(y-y0)^2 <= x^2+y^2
化简得:
2*x0*x+2*y0*y >= x0^2+y0^2
然后我们就可以把一个点当成一条线,一个圆当成一个点,通过上面的表达式来转换,这样“点在圆内”的关系就转化成了“点在半平面内”的关系。这样原问题就转化成了不断的加点,然后询问是否所有点都在某个半平面中。
这个东西因为“某一个点在不在半平面中”对”所有点都在半平面中“的答案贡献独立(前者拥有一票否决权),又没有强制在线,所以可以使用对时间分治的思想,以多一个log的复杂度将”边加点边询问问题“变成”先把所有点都加进去,再询问问题“,而后者可以在O(nlogn)时间复杂度内搞定,所以可以在O(nloglog)的时间复杂度内解决。
这道题开始看错题的限制了,题目中限制的是圆心坐标的范围,没有限制询问点坐标的范围,所以就挂了。
/**************************************************************
Problem: 2961
User: idy002
Language: C++
Result: Accepted
Time:6708 ms
Memory:96872 kb
****************************************************************/ #include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#define N 500010
#define eps 1e-10
using namespace std; int sg( double x ) { return (x>-eps)-(x<eps); }
struct Vector {
double x, y;
void read() {
scanf( "%lf%lf", &x, &y );
}
Vector(){}
Vector( double x, double y ):x(x),y(y){}
Vector operator+( const Vector &b ) const { return Vector(x+b.x,y+b.y); }
Vector operator-( const Vector &b ) const { return Vector(x-b.x,y-b.y); }
Vector operator*( double b ) const { return Vector(x*b,y*b); }
Vector operator/( double b ) const { return Vector(x/b,y/b); }
double operator^( const Vector &b ) const { return x*b.y-y*b.x; }
double operator&( const Vector &b ) const { return x*b.x+y*b.y; }
double ang() { return atan2l(y,x); }
bool operator<( const Vector &b ) const {
return sg(x-b.x)< || (sg(x-b.x)== && sg(y-b.y)<);
}
};
typedef Vector Point;
struct Line {
Point p;
Vector u;
double ang;
int id;
bool ok;
void read( int id ) {
double x, y;
double a, b, c;
scanf( "%lf%lf", &x, &y );
a=x+x, b=y+y;
c=x*x+y*y; if( sg(a)== && sg(b)== ) {
p.x = p.y = 0.0;
u.x = 1.0;
u.y = 0.0;
} else {
if( sg(a)!= )
p.x = c/a, p.y = 0.0;
else
p.x = 0.0, p.y = c/b;
u.x = -b, u.y = a;
if( sg(u^(Point(0.0,0.0)-p))>= )
u.x=-u.x, u.y=-u.y;
} ok = true;
this->id = id;
ang = u.ang();
}
};
struct Job {
int opt;
Point pt;
Line ln;
void read( int id ) {
scanf( "%d", &opt );
if( opt== ) pt.read();
else ln.read(id);
}
}; int n;
Job job[N];
int ans[N];
Point cvx[N];
double lang[N]; bool onleft( Line &l, Point &p ) { // <=
return sg( l.u^(p-l.p) ) >= ;
}
bool onleft( Point &a, Point &b, Point &p ) { // <
return sg( (b-a)^(p-a) ) > ;
}
int convex( vector<Point> &p ) {
sort( p.begin(), p.end() );
int n=p.size();
int m;
cvx[m=] = p[];
for( int i=; i<n; i++ ) {
while( m> && !onleft(cvx[m-],cvx[m],p[i]) ) m--;
cvx[++m] = p[i];
}
int k=m;
for( int i=n-; i>=; i-- ) {
while( m>k && !onleft(cvx[m-],cvx[m],p[i]) ) m--;
cvx[++m] = p[i];
}
return m; // n>=2
}
void binary( int lf, int rg, vector<Point> &vp, vector<Line> &vn ) {
if( lf==rg ) {
if( job[lf].opt== )
vp.push_back( job[lf].pt );
else
vn.push_back( job[lf].ln );
return;
}
vector<Point> lvp;
vector<Line> rvn;
int mid=(lf+rg)>>;
binary( lf, mid, lvp, vn );
binary( mid+, rg, vp, rvn );
//--
Point kpt;
if( lvp.empty() || rvn.empty() ) {
// do nothing
} else if( lvp.size()== ) {
for( int t=; t<rvn.size(); t++ ) {
if( !rvn[t].ok ) continue;
if( !onleft(rvn[t],lvp[]) )
rvn[t].ok = false;
}
} else {
int n = convex( lvp );
for( int t=; t<n; t++ )
lang[t] = (cvx[(t+==n?:t+)]-cvx[t]).ang();
int vid = ;
for( int t=; t<n; t++ )
if( lang[t]>lang[(t+==n?:t+)] ) {
vid = (t+==n?:t+);
break;
}
rotate( cvx, cvx+vid, cvx+n );
rotate( lang, lang+vid, lang+n );
for( int t=; t<rvn.size(); t++ ) {
if( !rvn[t].ok ) continue;
int tt;
if( rvn[t].ang<=lang[] || rvn[t].ang>=lang[n-] ) {
tt = ;
} else {
int lf=, rg=n-;
while( lf<rg ) {
int mid=(lf+rg)>>;
if( lang[mid]>rvn[t].ang ) {
rg = mid;
} else {
lf = mid+;
}
}
tt = lf;
}
int pt = tt==?n-:tt-;
int nt = tt==n-?:tt+;
if( !onleft(rvn[t],cvx[tt])
||!onleft(rvn[t],cvx[pt])
||!onleft(rvn[t],cvx[nt]) ) {
rvn[t].ok=false;
}
}
}
//--
for( int t=; t<lvp.size(); t++ )
vp.push_back( lvp[t] );
for( int t=; t<rvn.size(); t++ )
vn.push_back( rvn[t] );
}
int main() {
scanf( "%d", &n );
bool ok = false;
for( int i=; i<=n; i++ ) {
job[i].read(i);
job[i].ln.ok = ok;
if( job[i].opt== ) ok=true;
}
vector<Line> vn;
vector<Point> vp;
binary( , n, vp, vn );
for( int i=; i<=n; i++ )
ans[i] = -;
for( int t=; t<vn.size(); t++ )
ans[vn[t].id] = vn[t].ok;
for( int i=; i<=n; i++ ) {
if( ans[i]==- ) continue;
printf( "%s\n", ans[i] ? "Yes" : "No" );
}
}
bzoj 2961的更多相关文章
- bzoj 2961 共点圆 cdq+凸包+三分
题目大意 两种操作 1)插入一个过原点的圆 2)询问一个点是否在所有的圆中 分析 在圆中则在半径范围内 设圆心 \(x,y\) 查询点\(x_0,y_0\) 则\(\sqrt{(x-x_0)^2+(y ...
- zhengrui集训笔记2
Day_6 计算几何 点积\Large 点积点积 叉积\Large 叉积叉积 极角\Large 极角极角 < π\piπ :叉积判断 else :atan2 旋转\Large 旋转旋转 左乘第一 ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
- BZOJ 题目整理
bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
- 【清华集训】楼房重建 BZOJ 2957
Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...
随机推荐
- Python string interning原理
原文链接:The internals of Python string interning 由于本人能力有限,如有翻译出错的,望指明. 这篇文章是讲Python string interning是如何 ...
- MySQL 5.7.17 Group Relication(组复制)搭建手册【转】
本博文介绍了Group Replication的两种工作模式的架构.并详细介绍了Single-Master Mode的部署过程,以及如何切换到Multi-Master Mode.当然,文末给出了Gro ...
- HTTP之二 http 301 和 302的区别
1.什么是301转向?什么是301重定向? 301转向(或叫301重定向,301跳转)是当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种, ...
- 数据库-mysql数据操作
一:mysql 数据的插入 语法 以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法: INSERT INTO table_name ( field1, field2,...f ...
- asp.net mvc 本地化 默认的错误提示
System.ComponentModel.DataAnnotations 给我们提供了一些特性来直接对model的属性进行验证和约束, 同时也提供了 ErrorMessageResourceName ...
- java 学习网站
http://how2j.cn/ 教学网站 慕课视频下载网站 http://www.feemic.cn/mooc //慕课搜索和下载的网站http://www.soshoulu.com/tools/ ...
- Oracle学习笔记:trunc函数
在Oracle中可以使用trunc函数进行日期截取和数字截取,具体使用方法如下: 1.trunc(for dates) 日期截取 语法:trunc(date,[fmt]) select trunc(s ...
- gif处理
UleadGIFAnimator-v5.05破解版 网盘地址:https://pan.baidu.com/s/1bpf6iVP 2017-02-19 10:39:58
- Spark介绍及安装部署
一.Spark介绍 1.1 Apache Spark Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架(没有数据存储).最初在2009年由加州大学伯克利分校的AMPLab开 ...
- CCF CSP 201409-2 画图
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-2 画图 问题描述 在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y ...