4520: [Cqoi2016]K远点对

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

[Submit][Status][Discuss]

建立KD-Tree,用堆维护当前找到的前K远点对。

枚举一个点,在树中遍历,尝试更新堆顶(较近的点对)。

注意用KD-Tree“估价函数”来剪枝,还有因为点对有重复,所以应当取出第2K远的点对。

  1 #include <bits/stdc++.h>
  2
  3 const int siz = 100005;
  4
  5 int n, m;
  6
  7 struct node
  8 {
  9     int son[2];
 10     int pos[2];
 11     int maxi[2];
 12     int mini[2];
 13 }tr[siz];
 14
 15 int cmpk;
 16
 17 inline bool cmp(const node &a, const node &b)
 18 {
 19     if (a.pos[cmpk] != b.pos[cmpk])
 20         return a.pos[cmpk] < b.pos[cmpk];
 21     else
 22         return a.pos[cmpk^1] < b.pos[cmpk^1];
 23 }
 24
 25 int build(int l, int r, int k)
 26 {
 27     int mid = (l + r) >> 1; cmpk = k;
 28
 29     std::nth_element(tr + l, tr + mid, tr + r + 1, cmp);
 30
 31     if (l < mid)tr[mid].son[0] = build(l, mid - 1, k ^ 1);
 32     if (r > mid)tr[mid].son[1] = build(mid + 1, r, k ^ 1);
 33
 34     tr[mid].maxi[0] = tr[mid].mini[0] = tr[mid].pos[0];
 35     tr[mid].maxi[1] = tr[mid].mini[1] = tr[mid].pos[1];
 36
 37     for (int i = 0; i < 2; ++i)if (tr[mid].son[i])
 38         for (int j = 0; j < 2; ++j)
 39         {
 40             if (tr[mid].maxi[j] < tr[tr[mid].son[i]].maxi[j])
 41                 tr[mid].maxi[j] = tr[tr[mid].son[i]].maxi[j];
 42             if (tr[mid].mini[j] > tr[tr[mid].son[i]].mini[j])
 43                 tr[mid].mini[j] = tr[tr[mid].son[i]].mini[j];
 44         }
 45
 46     return mid;
 47 }
 48
 49 typedef long long lnt;
 50
 51 const lnt inf = 2e18;
 52
 53 std::priority_queue<
 54     lnt, std::vector<lnt>, std::greater<lnt>
 55 > heap;
 56
 57 int qx, qy;
 58
 59 inline lnt sqr(lnt x)
 60 {
 61     return x * x;
 62 }
 63
 64 inline lnt calc(int t)
 65 {
 66     lnt dx = std::max(sqr(tr[t].mini[0] - qx), sqr(tr[t].maxi[0] - qx));
 67     lnt dy = std::max(sqr(tr[t].mini[1] - qy), sqr(tr[t].maxi[1] - qy));
 68
 69     return dx + dy;
 70 }
 71
 72 void query(int t)
 73 {
 74     lnt dis = sqr(tr[t].pos[0] - qx) + sqr(tr[t].pos[1] - qy);
 75
 76     if (dis > heap.top())
 77     {
 78         heap.pop();
 79         heap.push(dis);
 80     }
 81
 82     lnt dl = tr[t].son[0] ? calc(tr[t].son[0]) : -inf;
 83     lnt dr = tr[t].son[1] ? calc(tr[t].son[1]) : -inf;
 84
 85     if (dl > dr)
 86     {
 87         if (dl > heap.top())query(tr[t].son[0]);
 88         if (dr > heap.top())query(tr[t].son[1]);
 89     }
 90     else
 91     {
 92         if (dr > heap.top())query(tr[t].son[1]);
 93         if (dl > heap.top())query(tr[t].son[0]);
 94     }
 95 }
 96
 97 signed main(void)
 98 {
 99     scanf("%d%d", &n, &m);
100
101     for (int i = 1; i <= n; ++i)
102         scanf("%d%d", &tr[i].pos[0], &tr[i].pos[1]);
103
104     int root = build(1, n, 0);
105
106     for (int i = 1; i <= 2*m; ++i)
107         heap.push(0LL);
108
109     for (int i = 1; i <= n; ++i)
110     {
111         qx = tr[i].pos[0];
112         qy = tr[i].pos[1];
113         query(root);
114     }
115
116     printf("%lld\n", heap.top());
117 }

@Author: YouSiki

转载于:https://www.cnblogs.com/yousiki/p/6284724.html

BZOJ 4520: [Cqoi2016]K远点对相关推荐

  1. 4520: [Cqoi2016]K远点对

    4520: [Cqoi2016]K远点对 Time Limit: 30 Sec   Memory Limit: 512 MB Submit: 594   Solved: 314 [ Submit][ ...

  2. 【52.55%】【BZOJ 4520】K远点对

    Time Limit: 30 Sec  Memory Limit: 512 MB Submit: 588  Solved: 309 [Submit][Status][Discuss] Descript ...

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

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

  4. BZOJ - 4520 K远点对

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

  5. P4357-[CQOI2016]K远点对【K-Dtree】

    正题 题目链接:https://www.luogu.com.cn/problem/P4357 题目大意 平面上给出nnn个点,求第kkk远的点对距离. 解题思路 K-Dtree\text{K-Dtre ...

  6. bzoj 4522: [Cqoi2016]密钥破解

    4522: [Cqoi2016]密钥破解 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 818  Solved: 480 [Submit][Stat ...

  7. BZOJ 3436 小K的农场 差分约束

    Description 背景 小K是个特么喜欢玩MC的孩纸... 描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得 一些含糊的信息(共m个 ...

  8. bzoj:3110: [Zjoi2013]K大数查询

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  9. BZOJ 3436: 小K的农场( 差分约束 )

    orz云神... 真的给跪了...BFS版spfa T 掉了...然后DFS版的就A了...我现在很迷茫.... 这就是个普通的差分约束... ---------------------------- ...

  10. [BZOJ]3436: 小K的农场

    题解:  差分约束 模板题 差分约束系统  联系 最短路 对于操作1:$ a-b\geqslant c\rightarrow b\leqslant a-c $ 也就是说a向b连一条-c的边 对于操作2 ...

最新文章

  1. Java 的 API、JDK 和 IDE 是什么
  2. icinga2+postgresql
  3. python unicodedecodeerror_如何解决python UnicodeDecodeError问题?
  4. 不出来信号 quartus_男人一旦动了真情,会向你发出这6个“信号”不爱的人装不出来...
  5. 初中数学最全几何模型_老师熬夜整理:初中数学最全几何模型大汇总,学生大呼“过瘾”...
  6. sql初学者指南_初学者SQL示例:SQL SELECT语句的用法
  7. 树-堆结构练习——合并果子之哈夫曼树(是最优二叉树题目的缩影)
  8. Convert.ToInt32()与int.Parse()的区别
  9. Google glass GDK - 通过MP3路径获取专辑图片
  10. 链脉企业文化篇之“链脉爱的早会”
  11. 简易打折,输入数量金额然后计算打折
  12. ps怎么将png做成gif_用ps将一组图片序列做成GIF
  13. grafana的前端二次开发初体验
  14. 学习C语言基本思路与参考书籍
  15. 武汉大学IT职业培训
  16. Android 实时滤镜 高斯模糊(带源码)
  17. 计算机内存和外存的主要特点,内存与外存的主要特点
  18. Android AOSP 源码 编译 android5.1.1,并刷入手机
  19. Winform(C#) 国内开源美化控件主题库2:花木兰控件库
  20. 小白鼠喝毒水的问题。

热门文章

  1. 计算机培训中学语文研修计划,初中语文个人研修计划书
  2. 51单片机自学好找工作吗,怎样学才能找到适合的工作
  3. 7.3 环境(Condition)
  4. [渝粤教育] 同济大学 线性代数学习指导 参考 资料
  5. 计算机网络基础系列(二)计算机网络体系结构
  6. HTML--day01
  7. [uva11997]k个最小和
  8. HTTP Session例子
  9. 图像sift配准后融合
  10. springmvc02,使用注解