UOJ#553【UNR #4】己酸集合【计算几何(圆内数点→半平面数点)】
题目描述
Link
二维平面 n n n 个点 ( x i , y i ) (x_i,y_i) (xi,yi), Q Q Q 次询问距离 ( 0 , z ) (0,z) (0,z) 小于等于 R R R 的点的数量。
n ≤ 12000 , Q ≤ 1 0 6 , ∣ x i ∣ , ∣ y i ∣ , ∣ z i ∣ , R ≤ 1 0 9 n\le12000,Q\le10^6,|x_i|,|y_i|,|z_i|,R\le10^9 n≤12000,Q≤106,∣xi∣,∣yi∣,∣zi∣,R≤109
题目分析
x 2 + ( y − z ) 2 ≤ R 2 x^2+(y-z)^2\le R^2 x2+(y−z)2≤R2
x 2 + y 2 ≤ R 2 − z 2 + 2 y z x^2+y^2\le R^2-z^2+2yz x2+y2≤R2−z2+2yz
( x , y ) → ( y , x 2 + y 2 ) (x,y)\to(y,x^2+y^2) (x,y)→(y,x2+y2)
y ′ ≤ k x ′ + b , k = 2 z , b = R 2 − z 2 y'\le kx'+b,k=2z,b=R^2-z^2 y′≤kx′+b,k=2z,b=R2−z2
问题转化为求平面某直线下的点数。维护在斜率确定下每个元素的偏序关系,询问就可以根据 b b b 二分了。
y − x k ≤ b y-xk\le b y−xk≤b
若对于某个确定的 k k k, x 1 x_1 x1 优于 x 2 x_2 x2, x 1 < x 2 x_1<x_2 x1<x2
则 y 1 − x 1 k ≤ y 2 − x 2 k y_1-x_1k\le y_2-x_2k y1−x1k≤y2−x2k
即 y 1 − y 2 ≤ k ( x 1 − x 2 ) ⟺ y 1 − y 2 x 1 − x 2 ≥ k y_1-y_2\le k(x_1-x_2) \Longleftrightarrow \frac {y_1-y_2}{x_1-x_2}\ge k y1−y2≤k(x1−x2)⟺x1−x2y1−y2≥k
初始时假设 k = − ∞ k=-\infty k=−∞, k k k 逐渐增大。
若 x 1 = x 2 x_1=x_2 x1=x2,则 y y y 小的恒更优。
所以初始排序时按照 x x x 为第一关键字, y y y 为第二关键字即可。
维护一个这样的偏序序列,当 k k k 达到某个值( ≤ n ( n − 1 ) / 2 \le n(n-1)/2 ≤n(n−1)/2 次交换)时,交换其中元素的顺序。
如果交换的位置不是相邻位,说明它们与中间的元素的交换时间重合了,时间重合的操作任意交换都是可以的。 前面这段划掉,假的。
这话相当于是在说如果把一个顺序排成逆序的选择排序的交换过程改为 n ( n − 1 ) / 2 n(n-1)/2 n(n−1)/2 次随机顺序的交换仍然可以排成逆序(显然是假的,比如 1 2 3 4 如果交换了 (1,2),(1,3),(3,4),那 1 就不可能排到末尾了)。
所以当交换操作时间相同时需要保证它是一个类似选择排序的过程,即交换时间相同的操作先按第一维排序,相同再按第二维排序。
注意这样我们还是不能保证每次交换的是相邻两位,因为可能有多个点分布在两个坐标,但是排序是可以正常进行的。
对这一段可以理解为一条旋转的扫描线,需要考虑的就是多点共线以及多点共坐标的情况。
直接做的复杂度是 O ( n 2 log n + Q log n ) O(n^2\log n+Q\log n) O(n2logn+Qlogn)
如果把点分成若干块处理,记分块大小为 S S S,那么复杂度变为 O ( ( S 2 + Q ) log n ∗ n S ) O((S^2+Q)\log n*\frac nS) O((S2+Q)logn∗Sn)
S = Q S=\sqrt Q S=Q 时最优, O ( n Q log n ) O(n\sqrt Q\log n) O(nQ logn)
PS:如果圆心坐标可以任取的话,问题就变成了三维半平面下数点(不过好像出题人说不会?手动狗头)
Code:
#include<bits/stdc++.h>
#define maxn 12005
#define maxq 1000005
#define LL long long
using namespace std;
char cb[1<<20],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<20,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &a){char c;bool f=0;while(!isdigit(c=getc())) c=='-'&&(f=1);for(a=c-'0';isdigit(c=getc());a=a*10+c-'0'); f&&(a=-a);
}
inline void write(int x){if(x>=10) write(x/10);putchar(x%10+48);
}
const int S = 1000;
int n,Q,ans[maxq];
struct node{LL x,y; int id;void init1(){read(y),read(x),y=x*x+y*y;}// x<=1e9void init2(int i){read(x),read(y),y=y*y-x*x,x*=2,id=i;}// x<=2e9bool operator < (const node &p)const{return x^p.x?x<p.x:y<p.y;}
}a[maxn],q[maxq],b[maxn];
struct change{double t;int x,y;bool operator < (const change &p)const{return t==p.t?x^p.x?x<p.x:y<p.y:t<p.t;}
}C[S*S]; int Cn;
int pos[maxn];
void mdf(int i,int j){if(pos[i]>pos[j]) return;//assert(pos[j]-pos[i]==1); assert failed.swap(b[pos[i]],b[pos[j]]);swap(pos[i],pos[j]);
}
void solve(node *a,int n){sort(a+1,a+1+n);Cn=0;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++) if(a[i].x!=a[j].x){double t=1.0*(a[i].y-a[j].y)/(a[i].x-a[j].x); if(t>=q[Q].x) continue;C[++Cn]=(change){t,i,j};}sort(C+1,C+1+Cn);for(int i=1;i<=n;i++) pos[i]=i;for(int i=1,j=1;i<=Q;i++){for(;j<=Cn&&C[j].t<q[i].x;j++) mdf(C[j].x,C[j].y);int l=0,r=n,mid;while(l<r) mid=(l+r+1)>>1,a[mid].y-a[mid].x*q[i].x<=q[i].y?l=mid:r=mid-1;ans[q[i].id]+=l;}
}
int main()
{read(n),read(Q);for(int i=1;i<=n;i++) a[i].init1();for(int i=1;i<=Q;i++) q[i].init2(i);sort(q+1,q+1+Q);for(int i=1;i<=n;i+=S){for(int j=1;j<=S&&i+j-1<=n;j++) b[j]=a[i+j-1];solve(b,min(S,n-i+1));}for(int i=1;i<=Q;i++) write(ans[i]),putchar('\n');
}
UOJ#553【UNR #4】己酸集合【计算几何(圆内数点→半平面数点)】相关推荐
- UOJ #277 BZOJ 4739 定向越野 (计算几何、最短路)
UOJ #277 BZOJ 4739 定向越野 (计算几何.最短路) 手动博客搬家: 本文发表于20181208 14:39:01, 原地址https://blog.csdn.net/suncongb ...
- Gym-100935I Farm 计算几何 圆和矩形面积交
题面 题意:就是给你一个圆,和你一个矩形,求面积并,且 保证是一种情况:三角剖分后 一个点在圆内 两个在圆外 题解:可以直接上圆与凸多边形交的板子,也可以由这题实际情况,面积等于扇形减两个三角形 1 ...
- python内置函数有哪些_Python集合有哪些内置函数可以使用,这些内置函数有什么功能...
Python 的元组与列表类似,不同之处在于元组的元素定义了就不能修改. 元组可以切片.可以循环.元组没有多少内置函数可以用. Python元组(tuple)包含了以下内置函数: len(tuple) ...
- Algorithm:C++语言实现之概率算法相关问题(计算机中的概率事件、C语言中的随机事件、产生二维随机数、圆内均匀取点)
Algorithm:C++语言实现之概率算法相关问题(计算机中的概率事件.C语言中的随机事件.产生二维随机数.圆内均匀取点) 目录 一.概率 1.计算机中的概率事件 1.1.C语言中的随机事件 1.2 ...
- Java黑皮书课后题第3章:**3.29(几何:两个圆)编写程序,提示用户输入两个圆的中心坐标和各自的半径值,然后判断圆是在第一个圆内,还是和第一个圆重叠
**3.29(几何:两个圆)编写程序,提示用户输入两个圆的中心坐标和各自的半径值,然后判断圆是在第一个圆内,还是和第一个圆重叠 题目 题目概述 运行示例 代码 题目 题目概述 **3.29(几何:两个 ...
- Java黑皮书课后题第3章:**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心、半径为10的圆内
**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心.半径为10的圆内 题目 题目概述 课本提示与举例.运行示例 破题 代码 两个浮点数的比 ...
- 有限覆盖定理证明区间套_圆内整点问题的开普勒猜想证明,关于圆内整点问题误差项的估值E(r)=1-x,x=sin(nx)...
将圆内整点问题视为格点对于圆的最大密度填充,用开普勒猜想证明,二维平面的 圆内整点问题误差项的估值 ,圆半径的格点数表示 , , 延拓至椭圆内整点问题结合皮克定理可应用于椭圆周长计算,当短长轴之比趋于 ...
- 判断一个点是否在指定的圆内
public static bool IsPointInCircle(myPoint p, myCircle circle) { //到圆心的距离 是否大于半径 ...
- Problem C: 点在圆内吗?
Description 定义一个Point类和Circle类,用于判断给定的一系列的点是否在给定的圆内. 其中,Point类: 1.有2个成员x和y,分别为其横坐标和纵坐标:1个静态成员numOfPo ...
最新文章
- 纯CSS3实现宽屏二级下拉菜单
- Swift中NSData与NSDictionary之间的相互转换
- 受疫情影响 AMD宣布退出CES线下展会
- 修炼!!!——超越项目经理
- 如何裁剪、合并视频?
- 机器学习笔记(三十二):集成学习、随机森林
- Java微服务系统项目技术栈总结
- win10系统个人服务器配置,个人电脑win10配置服务器吗
- 神来之笔,阿里最新Spring Security源码手册牵动了多少人的心,拿走不谢
- 只有长大了,才认识父亲
- 有关前端性能优化—DNS解析优化的方法?
- 收益率的分解 无风险利率
- golang 接口的底层实现
- Linux虚拟化之EXSI
- 【Django毕业设计源码】python在线办公系统
- 马哥架构第4周课程作业
- 低电平中断和下降沿中断的区别
- 老板丢给我一堆电话号码,让我挨个进行归属地、运营商查询
- 摄像模组中光学相关知识(二)
- 用MFC写一个随机抽号的软件(VS2013)