题解:P14634 [2018 KAIST RUN Fall] Voronoi Diagram Returns
P14634 Voronoi Diagram Returns
问题概述
给定平面上
对于每个查询点
- 某一个唯一区域 →
REGION i - 两个区域的公共边界 →
LINE i j - 三个以上区域的公共交点 →
POINT - 若不属于任何区域 →
NONE(实际不会发生)
为避免浮点误差,使用欧氏距离的平方:
核心思想
根据 Voronoi 图定义:
因此对每个查询点
- 遍历全部
P_i 计算距离平方d_i - 找到最小距离
d_{\min} - 统计有多少个
P_i 满足d_i = d_{\min}
结论如下:
Voronoi 图覆盖整个平面,因此 NONE 实际不会出现。
复杂度分析
对每个查询执行 O(n) 距离比较:
使用 C++ 的整数运算 + 关闭同步可在时限内通过。
样例分析
四个生成点:
查询 Q_1=(-2,2)
最小距离出现两次 → LINE 1 2
查询 Q_2=(0,0)
三次最小 → POINT
查询 Q_3=(2,2)
总结
本题不需要真正构建 Voronoi 图,只需判断“最小距离出现次数”。
暴力即可通过,代码短且稳定。
参考代码(C++)
// Problem: P14634 [2018 KAIST RUN Fall] Voronoi Diagram Returns
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P14634
// Memory Limit: 1024 MB
// Time Limit: 10000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,q;
cin>>n>>q;
vector<long long> px(n+1),py(n+1);
for(int i=1;i<=n;i++)
{
cin>>px[i]>>py[i];
}
while(q--)
{
long long x,y;
cin>>x>>y;
long long bestDist = 999999999999;
int cnt = 0;
int r1 = -1,r2 = -1;
for(int i=1;i<=n;i++)
{
long long dx = px[i]-x;
long long dy = py[i]-y;
long long d = dx*dx + dy*dy;
if(d<bestDist)
{
bestDist = d;
cnt = 1;
r1 = i;
r2 = -1;
}
else if(d==bestDist)
{
if(cnt==1)
{
cnt = 2;
r2 = i;
}
else if(cnt>=2)
{
cnt = 3;
}
}
}
if(cnt==0)
{
cout<<"NONE"<<endl;
}
else if(cnt==1)
{
cout<<"REGION "<<r1<<endl;
}
else if(cnt==2)
{
if(r1>r2) swap(r1,r2);
cout<<"LINE "<<r1<<" "<<r2<<endl;
}
else
{
cout<<"POINT"<<endl;
}
}
}
谢谢大家有耐心看完,加油!