zoukankan      html  css  js  c++  java
  • 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 long LL;
    const int N=200000;
    inline int read(){
        int 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;
    }
    struct data{
        LL dis;
        data(){};
        data(const LL&x){dis=x;}
        bool operator <(const data&x)const{return dis>x.dis;}
    }tmp;
    priority_queue<data>q;
    namespace KD_Tree{
        struct Dot{  
            int d[2],mn[2],mx[2],l,r;  
            Dot(){l=r=0;}  
            Dot(int x,int y){d[0]=x;d[1]=y;l=r=0;}  
            int& operator [] (int x){return d[x];}  
        };  
        int D,dcnt=0,pt[N]; 
        Dot T[N],p[N];
        bool operator<(Dot a,Dot b){return a[D]<b[D];}
        inline void umax(int&a,int b){if(a<b)a=b;}
        inline void umin(int&a,int b){if(a>b)a=b;}
        inline bool cmp(int x,int y){return T[x][D]<T[y][D];}
        inline void up(int x){
            T[x].mn[0]=T[x].mx[0]=T[x][0];  
            T[x].mn[1]=T[x].mx[1]=T[x][1]; 
            if(T[x].l){
                umax(T[x].mx[0],T[T[x].l].mx[0]);
                umin(T[x].mn[0],T[T[x].l].mn[0]);   
                umax(T[x].mx[1],T[T[x].l].mx[1]);
                umin(T[x].mn[1],T[T[x].l].mn[1]);
            }
            if(T[x].r){
                umax(T[x].mx[0],T[T[x].r].mx[0]);
                umin(T[x].mn[0],T[T[x].r].mn[0]);
                umax(T[x].mx[1],T[T[x].r].mx[1]);
                umin(T[x].mn[1],T[T[x].r].mn[1]);
            }
        }
        void AddDot(int x,int y){
            ++dcnt; pt[dcnt]=dcnt;
            p[dcnt][0]=x; p[dcnt][1]=y;
        }
        int build(int l,int r,int now){
        	if(l>r)return 0;
            int mid=(l+r)>>1;
            D=now;
            nth_element(p+l,p+mid,p+r+1);
            T[mid]=p[mid];
            for(int i=0;i<2;i++)T[mid].mn[i]=T[mid].mx[i]=T[mid][i];
            if(l<mid)T[mid].l=build(l,mid-1,now^1);
            if(r>mid)T[mid].r=build(mid+1,r,now^1);
            return up(mid),mid;
        }
        LL sqr(LL x){return x*x;}
        inline LL dist(int x,int px,int py){
            LL dis=0;
            if(!x)return 0;
                dis+=max(sqr(T[x].mn[0]-px),sqr(T[x].mx[0]-px));
                dis+=max(sqr(T[x].mn[1]-py),sqr(T[x].mx[1]-py));
                return dis;
            }
        }
        void query(int x,int px,int py){
            if(!x)return;
            LL dl,dr,d0=sqr(T[x][0]-px)+sqr(T[x][1]-py);
            dl=T[x].l?dist(T[x].l,px,py):0;
            dr=T[x].r?dist(T[x].r,px,py):0;
            if(d0>q.top().dis)q.pop(),q.push(data(d0));
            if(dl>dr){
                if(dl>q.top().dis)query(T[x].l,px,py);
                if(dr>q.top().dis)query(T[x].r,px,py);
            }
            else{
                if(dr>q.top().dis)query(T[x].r,px,py);
                if(dl>q.top().dis)query(T[x].l,px,py);
            }
        }
    }
    int n,k;
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)KD_Tree::AddDot(read(),read());
        int root=KD_Tree::build(1,n,0);
        for(int i=0;i<k+k;i++)q.push(tmp);
        for(int i=1;i<=n;i++)KD_Tree::query(root,KD_Tree::p[i][0],KD_Tree::p[i][1]);
        printf("%lld
    ",q.top().dis);
        return 0;
    }
    
  • 相关阅读:
    android选择时间攻略
    安卓通知的基本用法
    个人作业----软件工程实践总结
    第三次作业——《K米评测》
    第二次结对编程作业——毕设导师智能匹配
    原型设计与需求分析
    作品调研
    软件工程的实践项目课程的自我目标
    软件工程实践总结作业20161231
    K米测试
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj4520.html
Copyright © 2011-2022 走看看