Time Limit: 30 Sec  Memory Limit: 512 MB

Submit: 588  Solved: 309

[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

【题解】

第K远点对。是说C(N,2)个点对里面。点对之间的距离是第K远的。求这个距离。

我们枚举每个点。然后查看它与其他点的距离。

维护一个1..2*K远的队列。然后不断更新这个队列

(为什么是2*k,想想我们在枚举第一个点的时候,假如和第3个点配对,距离为第2远那么下次再枚举第3个点的时候还会遇到第一个点。又出现了一个第2远的数要加入到队列中。而这两个距离其实是同一个点对的。即排列。考虑其他第1,3,4,..k远的点对也会出现这种情况。我们就把K变成2*K。);

【代码】

  1. #include <cstdio>
  2. #include <algorithm>
  3.  
  4. using namespace std;
  5.  
  6. const int MAX_N = 109000;
  7.  
  8. int n, k,root,now;
  9. long long duilie[300];
  10.  
  11. struct point
  12. {
  13. long long d[2], mi_n[2], ma_x[2] ;
  14. int l,r;
  15. };
  16.  
  17. point t[MAX_N],op;
  18.  
  19. void input_data()
  20. {
  21. scanf("%d%d", &n, &k);
  22. for (int i = 1; i <= n; i++)
  23. scanf("%lld%lld", &t[i].d[0], &t[i].d[1]);
  24. }
  25.  
  26. bool cmp(point a, point b)
  27. {
  28. return a.d[now] < b.d[now];
  29. }
  30.  
  31. void up_data(int rt)
  32. {
  33. int l = t[rt].l, r = t[rt].r;
  34. for (int i = 0; i <= 1; i++)
  35. {
  36. if (l)
  37. {
  38. t[rt].ma_x[i] = max(t[rt].ma_x[i], t[l].ma_x[i]);
  39. t[rt].mi_n[i] = min(t[rt].mi_n[i], t[l].mi_n[i]);
  40. }
  41. if (r)
  42. {
  43. t[rt].ma_x[i] = max(t[rt].ma_x[i], t[r].ma_x[i]);
  44. t[rt].mi_n[i] = min(t[rt].mi_n[i], t[r].mi_n[i]);
  45. }
  46. }
  47. }
  48.  
  49. int build(int begin, int end, int fx)
  50. {
  51. int m = (begin + end) >> 1;
  52. now = fx;
  53. nth_element(t + begin, t + m, t + end + 1, cmp);
  54. for (int i = 0; i <= 1; i++)
  55. t[m].ma_x[i] = t[m].mi_n[i] = t[m].d[i];
  56. if (begin < m)
  57. t[m].l = build(begin, m - 1, 1 - fx);
  58. if (m < end)
  59. t[m].r = build(m + 1, end, 1 - fx);
  60. up_data(m);
  61. return m;
  62. }
  63.  
  64. long long sqr(long long x)
  65. {
  66. return x*x;
  67. }
  68.  
  69. long long get_dis(int rt)
  70. {
  71. return sqr(t[rt].d[0] - op.d[0]) + sqr(t[rt].d[1] - op.d[1]);
  72. }
  73.  
  74. long long gujia(int rt)//估价函数
  75. {
  76. long long temp = 0;
  77. for (int i = 0; i <= 1; i++)
  78. temp += max(sqr(t[rt].mi_n[i] - op.d[i]), sqr(t[rt].ma_x[i] - op.d[i]));
  79. return temp;
  80. }
  81.  
  82. void query(int rt)
  83. {
  84. long long dis = get_dis(rt);
  85. int k_th = k;
  86. while (duilie[k_th] <= dis)//找到这个距离在队列中的合适位置。
  87. {
  88. k_th--;
  89. if (!k_th)
  90. break;
  91. }
  92. if (k_th != k)
  93. {
  94. for (int i = k; i >= k_th + 2; i--)
  95. duilie[i] = duilie[i - 1];//这个位置后面的数字往后挪。
  96. duilie[k_th + 1] = dis;
  97. }
  98. int l = t[rt].l, r = t[rt].r;
  99. long long gl = -1,gr = -1;
  100. if (l)
  101. gl = gujia(l);
  102. if (r)
  103. gr = gujia(r);
  104. if (gl < gr)
  105. {
  106. if (gr >= duilie[k])
  107. query(r);
  108. if (gl >= duilie[k])
  109. query(l);
  110. }
  111. else
  112. {
  113. if (gl >= duilie[k])
  114. query(l);
  115. if (gr >= duilie[k])
  116. query(r);
  117. }
  118. }
  119.  
  120. void get_ans()
  121. {
  122. root = build(1, n, 0);
  123. k = k * 2;//直接求2*k远
  124. for (int i = 1; i <= k; i++)//duilie[1..k]分别表示第1,2,3..远。因此它是递减队列。
  125. duilie[i] = 0;
  126. for (int i = 1; i <= n; i++)
  127. {
  128. op.d[0] = t[i].d[0], op.d[1] = t[i].d[1];
  129. query(root);
  130. }
  131. }
  132.  
  133. void output_ans()
  134. {
  135. printf("%lld\n", duilie[k]);
  136. }
  137.  
  138. int main()
  139. {
  140. //freopen("F:\\rush.txt", "r", stdin);
  141. input_data();
  142. get_ans();
  143. output_ans();
  144. return 0;
  145. }

【52.55%】【BZOJ 4520】K远点对的更多相关文章

  1. BZOJ - 4520 K远点对

    题意:已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对 维护大小为2k最小堆,KD树的估值用前面提到的做法 PS.网上有人估价是使用边界四个点的最值来独立枚举,然而这样写似乎过不了 #incl ...

  2. BZOJ 4520: [Cqoi2016]K远点对

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

  3. BZOJ 4520 [Cqoi2016]K远点对(KD树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4520 [题目大意] 求K远点对距离 [题解] 修改估价函数为欧式上界估价,对每个点进行 ...

  4. BZOJ 4520: [Cqoi2016]K远点对(k-d tree)

    Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1162  Solved: 618[Submit][Status][Discuss] Descripti ...

  5. BZOJ 4520: [Cqoi2016]K远点对 KDtree + 估价函数 + 堆

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 200000 #define inf 10000000000 ...

  6. [Cqoi2016]K远点对 K-Dtree

    4520: [Cqoi2016]K远点对 链接 bzoj 思路 用K-Dtree求点的最远距离. 求的时候顺便维护一个大小为2k的小根堆. 不知道为啥一定会对. 代码 #include <bit ...

  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远点对

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

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

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

随机推荐

  1. swiper踩过的哪些坑

    最近,苦恼于各种轮播的需求,每个自己都要自己写,写的挺烦的.终于,在网上发现了swiper插件,发现还是挺实用的,但其中还是踩过了不少的坑,其中有不少都是很简单的问题,但到发现的时候都是花了不少时间, ...

  2. List容器案例

    案例讲解 迭代模式 不暴露集合的内部结构,又让外部访问集合中的数据 package com.day1; public interface Iterator <T>{ public bool ...

  3. 小爬爬4:selenium操作

    1.selenium是什么? selenium: - 概念:是一个基于浏览器自动化的模块. - 和爬虫之间的关联? - 帮我我们便捷的爬取到页面中动态加载出来的数据 - 实现模拟登陆 - 基本使用流程 ...

  4. 一维数组的求平均成绩 Day06

    package com.sxt.arraytest1; /* * 求班里学生的平均成绩,以及成绩的综合 输出每个同学的成绩 */ import java.util.Arrays; import jav ...

  5. 基本的Sql编写注意事项

    基本的Sql编写注意事项 尽量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替. 不用NOT IN操作符,可以用NOT EXISTS或者外连接+替代. Oracle在执行IN子查询时,首 ...

  6. Java练习 SDUT-1255_小明A+B

    小明A+B Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 小明今年3岁了, 现在他已经能够认识100以内的非负整数, ...

  7. 阿里云IPv6 DDoS防御被工信部认定为“网络安全技术应用试点示范项目”

    ​​近日,阿里云数据中心骨干网IPv6 DDoS网络安全防御被工业和信息化部认定为“网络安全技术应用试点示范项目”,本次评选由工业和信息部网络安全管理局发起,从实用性.创新性.先进性.可推广性等维度展 ...

  8. linux下修改gcc编译器版本

    可以使用如下命令行来让 gcc 选择不同的 C++ 版本: g++ -std=c++11 main.cpp 在你的系统中,由于编译器或是编译器设定上的差别,操作也许有所不同.    

  9. 让 AE 输出 MPEG

    最近在做视频后期处理,但是我发现 AE 的文件都很大,大概一个 10 分钟视频 10G ,所以有什么办法让他输出的文件变小?一个方法是使用 MPEG 输出. 本文告诉大家如何让 AE 输出 MPEG ...

  10. H3C 命令行帮助特性(续)