【BZOJ-4520】K远点对 KD-Tree + 堆

4520: [Cqoi2016]K远点对

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 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 5
0 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1

Sample Output

9

HINT

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;
}
时间: 2024-10-13 16:17:38

【BZOJ-4520】K远点对 KD-Tree + 堆的相关文章

BZOJ 1941: [Sdoi2010]Hide and Seek(k-d Tree)

Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 1712  Solved: 932[Submit][Status][Discuss] Description 小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏. 但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义

BZOJ 4520 [Cqoi2016]K远点对(KD树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4520 [题目大意] 求K远点对距离 [题解] 修改估价函数为欧式上界估价,对每个点进行dfs, 因为是无向点对,在小根堆中保留前2k个距离, 不断更新堆顶元素即可. [代码] #include <cstdio> #include <algorithm> #include <queue> using namespace std; typedef long lo

BZOJ 2648: SJY摆棋子(K-D Tree)

Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 6051  Solved: 2113[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=5

KD tree

Kd-树 其实是K-dimension tree的缩写,是对数据点在k维空间中划分的一种数据结构.其实,Kd-树是一种平衡二叉树. 举一示例: 假设有六个二维数据点 = {(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间中.为了能有效的找到最近邻,Kd-树采用分而治之的思想,即将整个空间划分为几个小部分.六个二维数据点生成的Kd-树的图为: 对于拥有n个已知点的kD-Tree,其复杂度如下: 构建:O(log2n) 插入:O(log n) 删除:O(l

k-d tree模板练习

1. [BZOJ]1941: [Sdoi2010]Hide and Seek 题目大意:给出n个二维平面上的点,一个点的权值是它到其他点的最长距离减最短距离,距离为曼哈顿距离,求最小权值.(n<=500,000) 思路:k-d tree裸题. #include<cstdio> #include<algorithm> using namespace std; inline int read() { int x;char c; while((c=getchar())<'0'

K-D tree入门【更新ing】

久仰K-D tree大名已久,终于在合适的时候遇见了合适的水题入了坑入了门 K-D tree是什么 K-D tree是什么? 按名字上翻译来就是K维的树,就是一个用来维护K维空间的点的平衡二叉树 K-D tree有什么用 K-D tree可以进行空间上的操作,最经典的就是查询最近/最远 点对 还有很多我不知道 K-D tree的原理与实现 K-D tree,又有一个名字叫做划分树,与其原理相联系 类似于普通的平衡树,对于普通的平衡树的节点u,其左右子树分别是权值小于u的和权值大于u的,该节点就相

[转载]kd tree

[本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树

bzoj4520 [Cqoi2016]K远点对

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 远点对的距离的平方(一定是个整数). 将所有点建成kd

k-d tree算法详解

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 1.应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树就是其中一种. 索引结构中相似性查询有两种基本的方式:一种是范围查询(range searches),另一种是K近邻查询