【BZOJ-4520】K远点对 KD-Tree + 堆
2016-05-24 19:57
267 查看
4520: [Cqoi2016]K远点对
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 490 Solved: 237
[Submit][Status][Discuss]
Description
已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。Input
输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点的坐标。1 < = N < = 100000, 1 < = K < = 100, K < = N*(N−1)/2 , 0 < = X, Y < 2^31。
Output
输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。Sample Input
10 50 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1
Sample Output
9HINT
Source
Solution
正解似乎是维护凸包!@#%……不过KD Tree暴力搞就可以了,而且实测效率很高
具体的做法就是:先将平面上的所有点加入KDTree中,然后维护一个小根堆,枚举每个点进行询问
小根堆的用途及相当于当前最优解为小根堆的堆顶
Attention:
有些点会被计算两次,所以堆中实际是2*k个元素
注意开longlong,极限值的取值
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<cstdlib> using namespace std; long long read() { long long x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 100010 #define inf 100000000000000000LL int n,k,D; long long sqr(long long a) {return (long long)(a*a);} struct PointNode { int l,r; long long d[2],maxx[2],minn[2]; bool operator < (const PointNode & A) const {return d[D]<A.d[D];} PointNode (long long x=0,long long y=0) {l=r=0; d[0]=x; d[1]=y;} }p[maxn]; priority_queue<long long, vector<long long>, greater<long long> > heap; long long dis(PointNode A,PointNode B) {return sqr(A.d[1]-B.d[1])+sqr(A.d[0]-B.d[0]);} struct KDTreeNode { int rt; PointNode Point,tree[maxn<<1]; void Update(int now) { for (int i=0; i<=1; i++) { tree[now].minn[i]=tree[now].maxx[i]=tree[now].d[i]; if (tree[now].l) tree[now].minn[i]=min(tree[tree[now].l].minn[i],tree[now].minn[i]),tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]); if (tree[now].r) tree[now].minn[i]=min(tree[tree[now].r].minn[i],tree[now].minn[i]),tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]); } } int BuildTree(int l,int r,int dd) { int mid=(l+r)>>1; D=dd; nth_element(p+l,p+mid,p+r+1); tree[mid]=p[mid]; for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i]; if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1); if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1); Update(mid); return mid; } long long dist(int pl,PointNode P) { long long re=0; for (int i=0; i<=1; i++) re+=max(sqr(P.d[i]-tree[pl].minn[i]),sqr(P.d[i]-tree[pl].maxx[i])); return re; } void Query(int now) { long long dl,dr,d0; d0=dis(tree[now],Point); if (d0>heap.top()) heap.pop(),heap.push(d0); if (tree[now].l) dl=dist(tree[now].l,Point); else dl=-inf; if (tree[now].r) dr=dist(tree[now].r,Point); else dr=-inf; if (dl>dr) { if (dl>heap.top()) Query(tree[now].l); if (dr>heap.top()) Query(tree[now].r); } else { if (dr>heap.top()) Query(tree[now].r); if (dl>heap.top()) Query(tree[now].l); } } }KDTree; int main() { // freopen("farthest.in","r",stdin); // freopen("farthest.out","w",stdout); n=read(); k=read(); for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i]=PointNode(x,y); KDTree.rt=KDTree.BuildTree(1,n,0); for (int i=1; i<=k+k; i++) heap.push(0LL); for (int i=1; i<=n; i++) KDTree.Point=p[i],KDTree.Query(KDTree.rt); printf("%lld\n",heap.top()); return 0; }
相关文章推荐
- 一次Linux自动化部署尝试
- Android OpenGL20 setIdentityM,translateM,rotateM,multiplyMV等方法
- 如何截取视频的第一张图片
- 使用gethostname()函数和gethostbyname()函数获取主机相关信息
- 工具类系列-GenerateHtml
- string类的运算符重载
- adb常见命令。查看内存,内存占用率,抓取log等
- 第十三周--动物这样叫
- mysql_基础1
- UE中使用正则表达式
- ACM--打表--HDOJ 1999--不可摸数
- 打印1到最大的n位数
- Android 解决中文参数传递到服务器乱码问题
- QuickHull 快速凸包
- LoadRunner中winsocket协议学习
- iOS:Objective-C中Self和Super详解
- 一年犹太人读书64本中国人4本反映啥
- Unicode 转化 GB18030 编码 方法
- 我所知道的关于webview的知识
- C/c++语言sort函数如何使用