• K-D tree 解决K远点对问题


    • 通过 K-D tree 和一个优先队列,可以查询距离一个钦定点第 K 远的点。

    • 具体操作看起来似乎比较暴力。

      1. 首先将 K 个 “ 空 ” 的值存入队列。

      2. 暴力 dfs K-D tree 更新队列。

    • 所有点对中的第 K 远点对显然只需要将队列全局化。


     

    P2093 [国家集训队]JZPFAR  多组询问,K 较小。

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 #define ls    son[u][0]
      4 #define rs    son[u][1]
      5 #define inf 1e9
      6 using namespace std;
      7 int n,m,root,opt;
      8 int pos[100050];
      9 ll val[100050][2],x[2];
     10 ll L[100050][2],R[100050][2];
     11 int son[100050][2];
     12 struct node
     13 {
     14     int pos;
     15     ll    dis;
     16     bool operator<(const node &p)const
     17     {
     18         return dis==p.dis? pos<p.pos:dis>p.dis;
     19     }
     20 }num[100050];
     21 priority_queue<node >q;
     22 void calc_push(node u)
     23 {
     24     q.pop();
     25     q.push(u);
     26 }
     27 bool cmp(int a,int b){return val[a][opt]<val[b][opt];}
     28 void pushup(int u)
     29 {
     30     for(int i=0;i<2;++i)
     31     {
     32         L[u][i]=min(val[u][i],min(L[ls][i],L[rs][i]));
     33         R[u][i]=max(val[u][i],max(R[ls][i],R[rs][i]));
     34     }
     35 }
     36 void build(int &u,int l,int r,int k)
     37 {
     38     if(l>r)    return ;
     39     int mid=(l+r)>>1;    opt=k;
     40     sort(pos+l,pos+r+1,cmp);
     41     u=pos[mid];
     42     build(son[u][0],l,mid-1,k^1);
     43     build(son[u][1],mid+1,r,k^1);
     44     pushup(u);
     45 }
     46 ll dou(ll u)
     47 {
     48     return u*u;
     49 }
     50 void calc_point(int u)
     51 {
     52     num[u].dis=dou(x[0]-val[u][0])+dou(x[1]-val[u][1]);
     53 }
     54 void calc_KD(int u)
     55 {
     56     if(!u)    return ;
     57     ll a=max(dou(x[0]-L[u][0]),dou(x[0]-R[u][0]));
     58     ll b=max(dou(x[1]-L[u][1]),dou(x[1]-R[u][1]));
     59     num[u].dis=a+b;
     60 }
     61 void query(int u)
     62 {
     63     if(!u)    return ;
     64     calc_point(u);
     65     if(num[u]<q.top())    calc_push(num[u]);
     66     calc_KD(ls);
     67     calc_KD(rs);
     68     if(num[ls]<num[rs])
     69     {
     70         if(num[ls]<q.top())    query(ls);
     71         if(num[rs]<q.top())    query(rs);
     72     }
     73     else
     74     {
     75         if(num[rs]<q.top())    query(rs);
     76         if(num[ls]<q.top())    query(ls);
     77     }
     78 }
     79 int main()
     80 {
     81     L[0][0]=L[0][1]=inf;
     82     R[0][0]=R[0][1]=-inf;
     83     num[0].dis=-2;
     84     scanf("%d",&n);
     85     for(int i=1;i<=n;++i)
     86     {
     87         scanf("%lld%lld",&val[i][0],&val[i][1]);
     88         pos[i]=i;    num[i].pos=i;
     89     }
     90     build(root,1,n,0);
     91     scanf("%d",&m);
     92     while(m--)
     93     {
     94         scanf("%lld%lld%d",&x[0],&x[1],&n);
     95         while(!q.empty())    q.pop();
     96         while(n--)            q.push(node{inf,-1});
     97         query(root);
     98         printf("%d
    ",q.top().pos);
     99     }
    100     return 0;
    101 }
    View Code

     P4357 [CQOI2016]K远点对  一组询问,K 较大。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define ls son[u][0]
     4 #define rs son[u][1]
     5 #define inf 1e9
     6 using namespace std;
     7 int n,m,root,opt;
     8 ll dis[100050];
     9 ll x[100050][2],y[2];
    10 ll L[100050][2],R[100050][2];
    11 int pos[100050];
    12 int son[100050][2];
    13 priority_queue<ll ,vector<ll>, greater<ll> >q;
    14 bool cmp(int a,int b){return x[a][opt]<x[b][opt];}
    15 void pushup(int u)
    16 {
    17     for(int i=0;i<2;++i)
    18     {
    19         L[u][i]=min(x[u][i],min(L[ls][i],L[rs][i]));
    20         R[u][i]=max(x[u][i],max(R[ls][i],R[rs][i]));
    21     }
    22 }
    23 void build(int &u,int l,int r,int k)
    24 {
    25     if(l>r)    return ;    opt=k;
    26     sort(pos+l,pos+r+1,cmp);
    27     int mid=(l+r)>>1;    u=pos[mid];
    28     build(son[u][0],l,mid-1,k^1);
    29     build(son[u][1],mid+1,r,k^1);
    30     pushup(u);
    31 }
    32 ll dou(ll u)
    33 {
    34     return u*u;
    35 }
    36 void calc_point(int u)
    37 {
    38     dis[u]=dou(x[u][0]-y[0])+dou(x[u][1]-y[1]);
    39 }
    40 void calc_kd(int u)
    41 {
    42     if(!u)    return ;
    43     ll a=max(dou(L[u][0]-y[0]),dou(R[u][0]-y[0]));
    44     ll b=max(dou(L[u][1]-y[1]),dou(R[u][1]-y[1]));
    45     dis[u]=a+b;
    46 }
    47 void query(int u)
    48 {
    49     if(!u)    return ;
    50     calc_point(u);
    51     if(dis[u]>q.top())
    52     {
    53         q.pop();
    54         q.push(dis[u]);
    55     }
    56     calc_kd(ls);
    57     calc_kd(rs);
    58     if(dis[ls]>dis[rs])
    59     {
    60         if(dis[ls]>q.top())    query(ls);
    61         if(dis[rs]>q.top())    query(rs);
    62     }
    63     else
    64     {
    65         if(dis[rs]>q.top())    query(rs);
    66         if(dis[ls]>q.top())    query(ls);
    67     }
    68 }
    69 int main()
    70 {
    71     L[0][0]=L[0][1]=inf;
    72     R[0][0]=R[0][1]=-inf;
    73     scanf("%d%d",&n,&m);m<<=1;
    74     for(int i=1;i<=n;++i)
    75     {
    76         scanf("%lld%lld",&x[i][0],&x[i][1]);
    77         pos[i]=i;
    78     }
    79     build(root,1,n,0);
    80     while(m--)    q.push(0);
    81     for(int i=n;i>=1;--i)
    82     {
    83         y[0]=x[i][0];
    84         y[1]=x[i][1];
    85         query(root);
    86     }
    87     printf("%lld",q.top());
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    自学传说中的php接口编写
    php数据类型
    php中的echo 与print 、var_dump 的区别
    vue 基础的一些字眼及路由
    初入 vue
    php 连接 数据库
    ExtJS获取父子、兄弟容器元素方法
    ext 的loadmask 与ajax的同步请求水火不容
    Ubuntu Server下配置UTF-8中文环境,ubuntu server zh_CN.UTF-8
    Proftpd快速搭建FTP服务器
  • 原文地址:https://www.cnblogs.com/wyher/p/10434285.html
Copyright © 2020-2023  润新知