首页 > 其他分享 >P7883 平面最近点对(加强加强版)

P7883 平面最近点对(加强加强版)

时间:2022-10-26 12:55:53浏览次数:78  
标签:return 加强版 point int res P7883 tr mid 平面

题目链接

P7883 平面最近点对(加强加强版)

题目背景

P1429 平面最近点对(加强版)里最高赞题解写道:

我们充分发扬人类智慧:
将所有点全部绕原点旋转同一个角度,然后按 \(x\) 坐标排序
根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远
所以我们只取每个点向后的 \(5\) 个点来计算答案
这样速度快得飞起,在 \(n=1000000\) 时都可以在 1 s 内卡过

当然,这是错的。

题目描述

给定 \(n\) 个二维欧几里得平面上的点 \(p_1, p_2, \dots, p_n\),请输出距离最近的两个点的距离。

输入格式

输入第一行为一个正整数 \(n\),表示点数。

接下来 \(n\) 行,第 \(i\) 行为用空格隔开的整数 \(x_i, y_i\),表示 \(p_i = (x_i, y_i)\)。

输入保证:没有两个坐标完全相同的点。

输出格式

输出一行,包含一个整数 \(D^2\),表示距离最近的两个点的距离的平方

由于输入的点为整点,因此这个值一定是整数。

样例 #1

样例输入 #1

2
-10000000 -10000000
10000000 10000000

样例输出 #1

800000000000000

样例 #2

样例输入 #2

5
1 1
1 9
9 1
9 9
0 10

样例输出 #2

2

提示

对于第二组样例,\((1, 9)\)、\((0, 10)\) 两个点最近,距离为 \(\sqrt 2\),因此你需要输出 \(2\)。

数据范围

对于 \(100 \%\) 的数据,\(2 \leq n \leq 4 \times 10^5\),\(-10^7 \leq x_i, y_i \leq 10^7\)。

本题目标复杂度是 \(O(n \log ^2 n)\)。设置 350ms 时限的原因是:

  1. \(O(n \log ^2 n)\) 参考代码使用 cin 不会 TLE。最快的 std 能 \(<\) 100ms。
  2. @wlzhouzhuan 的程序能恰好在 350ms 内跑 \(1000n\) 次检查。
  3. 150 组测试数据,为了防止卡评测。

解题思路

kdtree

kdtree 是一种能够高效处理 \(k\) 维空间的数据结构,当节点数远大于 \(2^k\) 时,kdtree 往往能取得很好的效果

以 \(2\) 维空间为例,按照某种划分原则以及选择某个维度(\(x\) 或 \(y\)),将某个点作为 kdtree 的根节点,假设选择的维度是 \(x\),则所有小于 \(x\) 的点作为左子树,其余点作为右子树,同理递归划分,一般选择中点进行划分,这样可以使左子树和右子树的节点数量尽量相等,使得树高为 \(O(logn)\) 级别,同时为了使 kdtree 上的节点的某一个维度不那么集中(主要是为了加快查询等操作),通常会选择方差较大的维度进行划分

本题可以枚举每个点,找到与其距离最近的点,由于 kdtree 上每个以节点为根的子树都可以表示为一个矩形,所以求出查询点和矩形的最近距离,如果该最近距离仍大于需要更新的答案的话,这棵子树中肯定没有更优解,即可以不用遍历该子树,另外可以进行启发式搜索:两棵子树中选择最近距离较近的子树搜索

对于矩阵查询,2dtree 单次时间复杂度最优 \(O(logn)\),最坏 \(O(\sqrt{n})\),扩展到 \(k\) 维,最坏时间复杂度:\(O(n^{1-\frac{1}{k}})\)

  • 最坏时间复杂度:\(O(n^2)\)

代码

// Problem: P7883 平面最近点对(加强加强版)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7883
// Memory Limit: 512 MB
// Time Limit: 350 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=4e5+5;
int n;
LL res=2e18;
struct Point
{
	int x,y;
}point[N];
struct Tr
{
	int s[2];
	int U,D,L,R;
}tr[N];
inline bool cmp1(Point &x,Point &y)
{
	return x.x<y.x;
}
inline bool cmp2(Point &x,Point &y)
{
	return x.y<y.y;
}
void pushup(int x)
{
	tr[x].L=tr[x].R=point[x].x;
	tr[x].U=tr[x].D=point[x].y;
	if(tr[x].s[0])
	{
		tr[x].L=min(tr[x].L,tr[tr[x].s[0]].L);
		tr[x].D=min(tr[x].D,tr[tr[x].s[0]].D);
		tr[x].R=max(tr[x].R,tr[tr[x].s[0]].R);
		tr[x].U=max(tr[x].U,tr[tr[x].s[0]].U);
	}
	if(tr[x].s[1])
	{
		tr[x].L=min(tr[x].L,tr[tr[x].s[1]].L);
		tr[x].D=min(tr[x].D,tr[tr[x].s[1]].D);
		tr[x].R=max(tr[x].R,tr[tr[x].s[1]].R);
		tr[x].U=max(tr[x].U,tr[tr[x].s[1]].U);
	}
}
LL dist(int x,int y)
{
	return (LL)(point[x].x-point[y].x)*(point[x].x-point[y].x)+(LL)(point[x].y-point[y].y)*(point[x].y-point[y].y);
}
LL get(int x,int y)
{
	LL res=0;
	if(point[y].x<tr[x].L)res+=(LL)(tr[x].L-point[y].x)*(LL)(tr[x].L-point[y].x);
	if(point[y].x>tr[x].R)res+=(LL)(tr[x].R-point[y].x)*(LL)(tr[x].R-point[y].x);
	if(point[y].y<tr[x].D)res+=(LL)(tr[x].D-point[y].y)*(LL)(tr[x].D-point[y].y);
	if(point[y].y>tr[x].U)res+=(LL)(tr[x].U-point[y].y)*(LL)(tr[x].U-point[y].y);
	return res;
}
void ask(int l,int r,int x)
{
	if(l>r)return ;
	int mid=l+r>>1;
	if(mid!=x)res=min(res,dist(x,mid));
	if(l==r)return ;
	LL distL=get(tr[mid].s[0],x),distR=get(tr[mid].s[1],x);
	if(distL<res&&distR<res)
	{
		if(distL<distR)
		{
			ask(l,mid-1,x);
			if(distR<res)ask(mid+1,r,x);
		}
		else
		{
			ask(mid+1,r,x);
			if(distL<res)ask(l,mid-1,x);
		}
	}
	else
	{
		if(distL<res)ask(l,mid-1,x);
		if(distR<res)ask(mid+1,r,x);
	}
}
int build(int l,int r)
{
	if(l>r)return 0;
	if(l==r)
	{
		pushup(l);
		return l;
	}
	int mid=l+r>>1;
	double avg[2]={0},va[2]={0};
	for(int i=l;i<=r;i++)avg[0]+=point[i].x,avg[1]+=point[i].y;
	avg[0]/=(double)(r-l+1),avg[1]/=(double)(r-l+1);
	for(int i=l;i<=r;i++)
		va[0]+=(point[i].x-avg[0])*(point[i].x-avg[0]),
		va[1]+=(point[i].y-avg[1])*(point[i].y-avg[1]);
	if(va[0]>=va[1])
		nth_element(point+l,point+mid,point+r+1,cmp1);
	else
		nth_element(point+l,point+mid,point+r+1,cmp2);
	tr[mid].s[0]=build(l,mid-1),tr[mid].s[1]=build(mid+1,r);
	pushup(mid);
	return mid;
}
int main()
{
	tr[0].L=tr[0].D=res,tr[0].R=tr[0].U=-res;
	read(n);
	for(int i=1;i<=n;i++)
    	read(point[i].x),read(point[i].y);
    sort(point+1,point+1+n,[](const Point &a,const Point &b){
    	if(a.x!=b.x)return a.x<b.x;
    	return a.y<b.y;
    });
    build(1,n);
    for(int i=1;i<=n;i++)ask(1,n,i);
    printf("%lld",LL(res));
    return 0;
}

标签:return,加强版,point,int,res,P7883,tr,mid,平面
From: https://www.cnblogs.com/zyyun/p/16827944.html

相关文章

  • Solidworks 2020总是显示3D效果,不能消失平面效果
    打开SolidWorks2020装配体后,通过快捷方式Space正视于前视基准面或者其他基准面后,总是显示3D效果,不能显示2D效果,就像轴测图一样,如下:解决办法:在设计树上的“前视基准面”......
  • 多重循环~平面分割
    题目描述:输入第一行输入一个整数m(m<=100),表示有m组测试数据。接下来的m行,每行有两个整数n和p,分别表示平面内的直线数和相交于一点直线数。 输出每组测试数据输出......
  • 平面计算几何基础-by chenkehan @fdu
    平面计算几何基础计算几何要解决什么问题?处理点、直线、线段、圆、多边形等几何图形的位置关系。浮点数相关存储方式:符号位F+指数位Z(阶码)+尾数位W\(x=F\timesW\time......
  • 点到平面距离
       应用于视锥体裁剪 http://www.lighthouse3d.com/tutorials/view-frustum-culling/clip-space-approach-extracting-the-planes/http://www.lighthouse3d.com/t......
  • 【Unity】控制物体平面移动的几种方法
    一、WASD键控制物体前后左右移动一定的距离voidmyMove(){if(Input.GetKeyDown(KeyCode.D)||Input.GetKeyDown(KeyCode.RightArrow)){......
  • [CQOI2006]凸多边形 /【模板】半平面交
    洛谷题意:逆时针给出\(n(n<=10)\)个凸多边形的顶点坐标,求它们交的面积。学长博客,计算几何知识全面半平面交问题详细讲解还有一些前置知识。两向量\((x_1,y_1),(x_2,y_2)......
  • 《大话设计模式 Java溢彩加强版》相关主题
    《大话设计模式Java溢彩加强版》读者须知     《大话设计模式Java溢彩加强版》在2022年10月在各大网上书店中有售!源代码与课件下载 《大话设计模式Java溢彩......
  • 【电子元器件检测设备】3D激光平面度检测设备适用范围及特点
    众所周知,产品生产出来之后都有一步关键性的操作:那就是产品品质检测,电子元器件也一样。今天,小编来给大家介绍一款秦泰盛自主研发生产专为电子加工行业精心设计的一种高精度测......
  • 【PCL模块解析 07 之 点云分割】01 平面模型分割
    目录​​一、前言​​​​二、PCL简介​​​​1、PCL简介​​​​2、PCL分割​​​​三、平面模型分割​​​​1、全部代码​​​​2、分块介绍​​​​1.创建数据​​​​2......
  • 平面图最小割转换为对偶图最短路问题
    1、P4001[ICPC-Beijing2006]狼抓兔子 P4001[ICPC-Beijing2006]狼抓兔子-洛谷|计算机科学教育新生态(luogu.com.cn)直接上图,  注意dijkstra!!!  判重......