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. cmake-index-3.11.4机翻

    index next | CMake » git-stage git-master latest release 3.13 3.12 3.11.4 3.10 3.9 3.8 3.7 3.6 3.5 3 ...

  2. Paper Reading - Long-term Recurrent Convolutional Networks for Visual Recognition and Description ( CVPR 2015 )

    Link of the Paper: https://arxiv.org/abs/1411.4389 Main Points: A novel Recurrent Convolutional Arch ...

  3. 华为中兴借eBay出海 靠零售渠道撬动市场

    在跨境电商领域,大多数中国商家依靠“中国制造”的优势和价格战策略打拼出一条血路,在海外市场占领了自己的一席 之地.不过,山寨货纷纷出海的同时,中国本土的品牌商们也开始了探索海外市场之旅.目前,华为.中 ...

  4. ASP.NET MVC - 启动创建项目,未能加载错误

    VS2012以常规方式创建一ASP.NET MVC internet 项目.创建后F5启动项目,遇一错误: 未能加载文件或程序集“MySql.Web.v20, Version=6.9.4.0, Cul ...

  5. USACO 1.3.3 Calf Flac(Manacher算法)

    Description 据说如果你给无限只母牛和无限台巨型便携式电脑(有非常大的键盘),那么母牛们会制造出世上最棒的回文.你的工作就是去寻找这些牛制造的奇观(最棒的回文). 在寻找回文时不用理睬那些标 ...

  6. 20181120-10 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 7

    此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2415] 版本控制地址    [https://git.coding.n ...

  7. 20172330 2017-2018-1 《Java程序设计》第十一周学习总结

    20172330 2017-2018-1 <程序设计与数据结构>第十一周学习总结 教材学习内容总结 本周的学习内容为集合 Android简介 Android操作系统是一种多用户的Linux ...

  8. c语言学习—图书搜索

    请问下:你说的C四大圣经指那几本啊?——<C 陷阱与缺陷> && <C程序设计语言> && <C专家编程> && & ...

  9. php 多维数组排序

    PHP中array_multisort可以用来一次对多个数组进行排序,或者根据某一维或多维对多维数组进行排序. 关联(string)键名保持不变,但数字键名会被重新索引. 输入数组被当成一个表的列并以 ...

  10. i18n实现前端国际化(实例)

    在今日的需求中需要利用 i18n 这个框架来实现前端的国家化操作,下图是实现效果: 点击选择框实现网页上语言的切换: 下面开始实现过程: 所需工具:    - jquery-3.3.1.js 下载地址 ...