• [BZOJ4520][Cqoi2016]K远点对 kd-tree 优先队列


    4520: [Cqoi2016]K远点对

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 1285  Solved: 708
    [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

    kd-tree可以查询每个点到其他点的距离。

    我们求出每两个点间的距离,随后求出第2*k大值即可。

    用优先队列维护前2*k大值,在kd-tree上查询并修改即可。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #define ll long long
     9 #define maxn 100005
    10 using namespace std;
    11 inline int read() {
    12     int x=0,f=1;char ch=getchar();
    13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    15     return x*f;
    16 }
    17 int nowd=0,rt,n,k;
    18 struct node {ll d[2],mx[2],mn[2],l,r;}t[maxn];
    19 bool cmp(node t1,node t2) {return t1.d[nowd]<t2.d[nowd];}
    20 priority_queue<ll,vector<ll>,greater<ll> >q;ll cnt=0;
    21 void pushup(int x) {
    22     int l=t[x].l,r=t[x].r;
    23     if(l) {
    24         t[x].mx[0]=max(t[x].mx[0],t[l].mx[0]);
    25         t[x].mx[1]=max(t[x].mx[1],t[l].mx[1]);
    26         t[x].mn[0]=min(t[x].mn[0],t[l].mn[0]);
    27         t[x].mn[1]=min(t[x].mn[1],t[l].mn[1]);
    28     }
    29     if(r) {
    30         t[x].mx[0]=max(t[x].mx[0],t[r].mx[0]);
    31         t[x].mx[1]=max(t[x].mx[1],t[r].mx[1]);
    32         t[x].mn[0]=min(t[x].mn[0],t[r].mn[0]);
    33         t[x].mn[1]=min(t[x].mn[1],t[r].mn[1]);
    34     }
    35 }
    36 int build(int l,int r,bool D) {
    37     int mid=l+r>>1;nowd=D;
    38     nth_element(t+l,t+mid,t+r+1,cmp);
    39     if(l<mid) t[mid].l=build(l,mid-1,!D);
    40     if(r>mid) t[mid].r=build(mid+1,r,!D);
    41     t[mid].mx[0]=t[mid].mn[0]=t[mid].d[0];
    42     t[mid].mx[1]=t[mid].mn[1]=t[mid].d[1];
    43     pushup(mid);
    44     return mid;
    45 }
    46 ll dis(int x,int y) {return (t[x].d[0]-t[y].d[0])*(t[x].d[0]-t[y].d[0])+(t[x].d[1]-t[y].d[1])*(t[x].d[1]-t[y].d[1]);}
    47 ll gdis(int x,int y) {
    48     return max((t[x].mn[0]-t[y].d[0])*(t[x].mn[0]-t[y].d[0]),(t[x].mx[0]-t[y].d[0])*(t[x].mx[0]-t[y].d[0]))+max((t[x].mn[1]-t[y].d[1])*(t[x].mn[1]-t[y].d[1]),(t[x].mx[1]-t[y].d[1])*(t[x].mx[1]-t[y].d[1]));
    49 }
    50 void query(int x,int y) {
    51     if(!x) return;
    52     ll now=dis(x,y);
    53     if(now>q.top()) {q.pop();q.push(now);}
    54     ll dl=0,dr=0;
    55     if(t[x].l) dl=gdis(t[x].l,y);if(t[x].r) dr=gdis(t[x].r,y);
    56     if(dl>dr) {
    57         if(dl>q.top()) query(t[x].l,y);
    58         if(dr>q.top()) query(t[x].r,y);
    59     }
    60     else {
    61         if(dr>q.top()) query(t[x].r,y);
    62         if(dl>q.top()) query(t[x].l,y);
    63     }
    64 }
    65 int main() {
    66     n=read();k=read();
    67     for(int i=1;i<=n;i++) t[i].d[0]=read(),t[i].d[1]=read();
    68     rt=build(1,n,0);
    69     for(int i=1;i<=k*2;i++) q.push(0);
    70     for(int i=1;i<=n;i++) query(rt,i);
    71     printf("%lld
    ",q.top());
    72 }
    View Code
  • 相关阅读:
    全面兼容的Iframe 与父页面交互操作
    Windows Phone 8.1 新特性
    android手电筒源码
    最新android版QQ布局效果 v4.7.0全新UI源码
    点击弹出动态菜单效果ios源码
    本app(仿手机支付宝界面)ios源码
    WP应用开发笔记
    关于移动,爱游,联通三家运营商付费SDK的融合方案
    cocos2d-x学习总结01引言
    新站seo如何进行站内优化
  • 原文地址:https://www.cnblogs.com/wls001/p/9708908.html
Copyright © 2020-2023  润新知