zoukankan      html  css  js  c++  java
  • 【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
    ",heap.top());
        return 0;
    }
  • 相关阅读:
    nginx thinkphp rewrite配置项
    mysql主从配置,主从服务器都是全新安装myql的情景
    mysql提示启动成功,但statu是isstopped,重启后正常
    mysql怎么设置密码都不正确的一个解决方法
    linux统计文件个数及代码总行数
    mysqld启动失败时日志查看命令
    .tar.xz 的解压方式 centos
    CentOS 安装Erlang
    vector android:fillType gradient android:endX attribute not found
    found an invalid color
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5524645.html
Copyright © 2011-2022 走看看