Portal --> bzoj4520

Description

  给你平面内\(n\)个点的坐标,求欧氏距离下第\(k\)远的点对

Solution

  因为kd其实。。严格来说挺不熟的用的太少了qwq

  然后不知道为啥第一反应凸包直径取\(k\)次qwq然而这样有一个问题就是。。取完一次之后删点不知道要删直径中两个点中的哪一个,所以。。不太靠谱

  正解应该是kd-tree

  其实这题挺暴力的,时间复杂度也很玄学(不会算qwq)貌似kd的题复杂度就没有不玄学的。。

  因为不知道答案是哪两个点,初步的想法是我们干脆维护一个大小为\(k\)的小根堆,对于每一个点,都在kd-tree里面查以其作为两个点之一的点对的前\(k\)大距离,如果说比小根堆的堆顶更优那就用当前的结果把小根堆的堆顶替换掉,这样对每一个点都操作一遍之后,堆顶就是答案了

​  然而实际上,我们会发现一个点对会被计算两次,所以我们其实应该维护一个\(k*2\)的堆,查找也是\(k*2\)而不是\(k\)

  再稍微具体一点的话在kd中查找的流程大概是这样的:

1、计算当前点与固定点的距离,如果比堆顶优就替换

2、用一个估值函数分别计算两个子树的可能最远距离\(lval\)和\(rval\)

3、如果说\(lval>rval\)则优先遍历左子树,否则优先遍历右子树

4、遍历一个子树的前提条件是:当前堆中不足\(k*2\)个元素或者该子树的估值函数返回值优于堆顶

  接下来就是这个估值函数要怎么写了:

  (这里提供的这种写法比较。。水。。其实如果有心去卡的话貌似是可以卡掉的qwq)

  我们考虑分别记录该子树内的\(x\)的最大最小值和\(y\)的最大最小值,然后估值函数就返回\(x\)的最大最小值与固定点的\(x\)的最大差值的平方+\(y\)的最大最小值与固定点的\(y\)的最大差值的平方,这样我们就能得到一个最优情况下的最大值了

  

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=100010,inf=2147483647;
int which;
ll sqr(ll x){return x*x;}
struct Dot{
int data[2];
Dot(){}
Dot(int x,int y){data[0]=x; data[1]=y;}
friend ll dis(Dot a,Dot b){return sqr(a.data[0]-b.data[0])+sqr(a.data[1]-b.data[1]);}
friend bool operator < (Dot a,Dot b){return a.data[which]<b.data[which];}
}a[N];
int n,k,tot;
bool cmp(ll x,ll y){return x>y;}
priority_queue<ll,vector<ll>,greater<ll> > q;
namespace Kd{/*{{{*/
int ch[N][2],mnx[N],mxx[N],mny[N],mxy[N];
int rt;
void pushup(int x){
mxx[x]=mnx[x]=a[x].data[0]; mxy[x]=mny[x]=a[x].data[1];
if (ch[x][0]){
mxx[x]=max(mxx[x],mxx[ch[x][0]]);
mxy[x]=max(mxy[x],mxy[ch[x][0]]);
mnx[x]=min(mnx[x],mnx[ch[x][0]]);
mny[x]=min(mny[x],mny[ch[x][0]]);
}
if (ch[x][1]){
mxx[x]=max(mxx[x],mxx[ch[x][1]]);
mxy[x]=max(mxy[x],mxy[ch[x][1]]);
mnx[x]=min(mnx[x],mnx[ch[x][1]]);
mny[x]=min(mny[x],mny[ch[x][1]]);
}
}
int _build(int l,int r,int now){
if (l>r) return 0;
int mid=l+r>>1;
which=now;
nth_element(a+l,a+mid,a+r+1);
ch[mid][0]=_build(l,mid-1,now^1);
ch[mid][1]=_build(mid+1,r,now^1);
pushup(mid);
return mid;
}
ll val(int x,Dot &delta){
if (!x) return -1;
ll ret=max(sqr(delta.data[0]-mnx[x]),sqr(delta.data[0]-mxx[x]))+
max(sqr(delta.data[1]-mny[x]),sqr(delta.data[1]-mxy[x]));
return ret;
}
void build(int n){rt=_build(1,n,0);}
void _query(int x,int k,Dot &delta){
if (!x) return;
ll d=dis(delta,a[x]),lval=val(ch[x][0],delta),rval=val(ch[x][1],delta);
if (q.size()<k) q.push(d);
else{
if (d>q.top())
q.pop(),q.push(d);
}
if (lval>rval){
if (lval>q.top()||q.size()<k) _query(ch[x][0],k,delta);
if (rval>q.top()||q.size()<k) _query(ch[x][1],k,delta);
}
else{
if (rval>q.top()||q.size()<k) _query(ch[x][1],k,delta);
if (lval>q.top()||q.size()<k) _query(ch[x][0],k,delta);
}
}
void query(Dot &delta,int k){_query(rt,k,delta);}
}/*}}}*/ int main(){
#ifndef ONLINE_JUDGE
freopen("2.in","r",stdin);
#endif
scanf("%d%d",&n,&k);
for (int i=1;i<=n;++i)
scanf("%d%d",&a[i].data[0],&a[i].data[1]);
k*=2;
Kd::build(n);
tot=0;
for (int i=1;i<=n;++i) Kd::query(a[i],k);
printf("%lld\n",q.top());
}

【bzoj4520】K远点对的更多相关文章

  1. bzoj4520 K远点对

    题目链接 思路 这个"\(K\)远"点对一直理解成了距离第\(K\)大的点对\(233\). 要求第\(K\)远,那么我们只要想办法求出来最远的\(K\)个点对就可以了. 用一个大 ...

  2. 【bzoj4520】 Cqoi2016—K远点对

    http://www.lydsy.com/JudgeOnline/problem.php?id=4520 (题目链接) 题意 求平面内第K远点对的距离. Solution 左转题解:jump 细节 刚 ...

  3. 【BZOJ4520】K远点对(KD-Tree)

    [BZOJ4520]K远点对(KD-Tree) 题面 BZOJ 洛谷 题解 考虑暴力. 维护一个大小为\(K\)的小根堆,然后每次把两个点之间的距离插进去,然后弹出堆顶 这样子可以用\(KD-Tree ...

  4. 【BZOJ4520】[Cqoi2016]K远点对 kd-tree+堆

    [BZOJ4520][Cqoi2016]K远点对 Description 已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. Input 输入文件第一行为用空格隔开的两个整数 N, K.接下来 ...

  5. [bzoj4520][Cqoi2016]K远点对_KD-Tree_堆

    K远点对 bzoj-4520 Cqoi-2016 题目大意:已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. 注释:$1\le n\le 10^5$,$1\le k\le 100$,$k\l ...

  6. BZOJ4520 [Cqoi2016]K远点对

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

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

    4520: [Cqoi2016]K远点对 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 490  Solved: 237[Submit][Status ...

  8. BZOJ4520:[CQOI2016]K远点对(K-D Tree)

    Description 已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. Input 输入文件第一行为用空格隔开的两个整数 N, K.接下来 N 行,每行两个整数 X,Y,表示一个点 的坐标 ...

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

    4520: [Cqoi2016]K远点对 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1285  Solved: 708[Submit][Statu ...

随机推荐

  1. appium自动化环境搭建

    1.java开发环境JDK 2.android SDK(platform/platform tools/tools/build tools) 3.python下载安装(pip) 4.appium下载安 ...

  2. HDU-4055:Number String

    链接:HDU-4055:Number String 题意:给你一个字符串s,s[i] = 'D'表示排列中a[i] > a[i+1],s[i] = 'I'表示排列中a[i] < a[i+1 ...

  3. 408. Add Binary【LintCode java】

    Description Given two binary strings, return their sum (also a binary string). Example a = 11 b = 1 ...

  4. hive的简单使用

    一.一些说明 1.支持的操作 hive 默认不支持updata 和 delete操作 insert也是执行缓慢,主要用于数据的计算 hive 数据类型---字符串,大部分与java一致. 2.内外表的 ...

  5. Docker虚拟机172.17网段冲突,导致网络访问问题

    在虚拟机中安装docker,linux ubuntu16 ,安装完公司172.17网段被docker0覆盖,导致ssh无法连接到ubuntu. 经过官网的这篇build your own bridge ...

  6. [转载]linux+nginx+python+mysql安装文档

    原文地址:linux+nginx+python+mysql安装文档作者:oracletom # 开发包(如果centos没有安装数据库服务,那么要安装下面的mysql开发包) MySQL-devel- ...

  7. eos对数据库的操作

    eosio的multi_index 概述 multi_index是eosio上的数据库管理接口,通过eosio::multi_index智能合约能够写入.读取和修改eosio数据库的数据 multi_ ...

  8. 如何把node更新到最新的稳定版本

    先装n,再用n把node升级到最新稳定版 $ npm install -g n $ n stable

  9. Alpha冲刺——第十天

    Alpha第十天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  10. 团队作业4——第一次项目冲刺(Alpha版本)第一次

    一.会议内容 制定任务内容 制作leangoo表格 初步工作 二.各人工作 成员 计划任务 遇见难题 贡献比 塗家瑜(组长) 后端与数据库通讯 无 1 张新磊 表设计 无 1 姚燕彬 测试计划编写 无 ...