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。);

【代码】

#include <cstdio>
#include <algorithm> using namespace std; const int MAX_N = 109000; int n, k,root,now;
long long duilie[300]; struct point
{
long long d[2], mi_n[2], ma_x[2] ;
int l,r;
}; point t[MAX_N],op; void input_data()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &t[i].d[0], &t[i].d[1]);
} bool cmp(point a, point b)
{
return a.d[now] < b.d[now];
} void up_data(int rt)
{
int l = t[rt].l, r = t[rt].r;
for (int i = 0; i <= 1; i++)
{
if (l)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[l].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[l].mi_n[i]);
}
if (r)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[r].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[r].mi_n[i]);
}
}
} int build(int begin, int end, int fx)
{
int m = (begin + end) >> 1;
now = fx;
nth_element(t + begin, t + m, t + end + 1, cmp);
for (int i = 0; i <= 1; i++)
t[m].ma_x[i] = t[m].mi_n[i] = t[m].d[i];
if (begin < m)
t[m].l = build(begin, m - 1, 1 - fx);
if (m < end)
t[m].r = build(m + 1, end, 1 - fx);
up_data(m);
return m;
} long long sqr(long long x)
{
return x*x;
} long long get_dis(int rt)
{
return sqr(t[rt].d[0] - op.d[0]) + sqr(t[rt].d[1] - op.d[1]);
} long long gujia(int rt)//估价函数
{
long long temp = 0;
for (int i = 0; i <= 1; i++)
temp += max(sqr(t[rt].mi_n[i] - op.d[i]), sqr(t[rt].ma_x[i] - op.d[i]));
return temp;
} void query(int rt)
{
long long dis = get_dis(rt);
int k_th = k;
while (duilie[k_th] <= dis)//找到这个距离在队列中的合适位置。
{
k_th--;
if (!k_th)
break;
}
if (k_th != k)
{
for (int i = k; i >= k_th + 2; i--)
duilie[i] = duilie[i - 1];//这个位置后面的数字往后挪。
duilie[k_th + 1] = dis;
}
int l = t[rt].l, r = t[rt].r;
long long gl = -1,gr = -1;
if (l)
gl = gujia(l);
if (r)
gr = gujia(r);
if (gl < gr)
{
if (gr >= duilie[k])
query(r);
if (gl >= duilie[k])
query(l);
}
else
{
if (gl >= duilie[k])
query(l);
if (gr >= duilie[k])
query(r);
}
} void get_ans()
{
root = build(1, n, 0);
k = k * 2;//直接求2*k远
for (int i = 1; i <= k; i++)//duilie[1..k]分别表示第1,2,3..远。因此它是递减队列。
duilie[i] = 0;
for (int i = 1; i <= n; i++)
{
op.d[0] = t[i].d[0], op.d[1] = t[i].d[1];
query(root);
}
} void output_ans()
{
printf("%lld\n", duilie[k]);
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
get_ans();
output_ans();
return 0;
}

【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. Directx11 教程(1) 基本的windows应用程序框架(1)

    原文:Directx11 教程(1) 基本的windows应用程序框架(1)        在vs2010中,建立一个新的win32工程,名字是: myTutorialD3D11, 注意:同时勾选Cr ...

  2. 微信小程序云数据库——where查询和doc查询区别

    用法 条件查询where 我们也可以一次性获取多条记录.通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录,比如获取用户的所有未完成的待办事项,用 ...

  3. hdu5131 贪心

    #include<stdio.h> #include<string.h> #include<algorithm> #include<string> #i ...

  4. execute和submit的区别与联系

    execute和submit都属于线程池的方法,execute只能提交Runnable类型的任务,而submit既能提交Runnable类型任务也能提交Callable类型任务. execute会直接 ...

  5. MaxCompute 图计算开发指南

    快速入门step by step MaxCompute Studio 创建完成 MaxCompute Java Module后,即可以开始开发Graph了. 代码示例 在examples目录下有gra ...

  6. HDU 5572 An Easy Physics Problem【计算几何】

    计算几何的题做的真是少之又少. 之前wa以为是精度问题,后来发现是情况没有考虑全... 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5572 题意: ...

  7. 2018-8-10-WPF-轻量级-MVVM-框架入门-2.1.2

    title author date CreateTime categories WPF 轻量级 MVVM 框架入门 2.1.2 lindexi 2018-08-10 19:16:51 +0800 20 ...

  8. 关于Lattice Planner规划算法的若干问答

    Apollo问答 | 关于Lattice Planner规划算法的若干问答   上周,我们在Apollo开发者交流群内做了关于Lattice Planner的分享.这里,我们将社群分享里开发者提出的问 ...

  9. Python基础:08列表解析与生成器表达式

    一:列表解析 列表解析(List comprehensions)来自函数式编程语言Haskell .它可以用来动态地创建列表.它在 Python 2.0 中被加入. 列表解析的语法:     [exp ...

  10. The Top 50 Proprietary Programs that Drive You Crazy — and Their Open Source Alternatives

    The Top 50 Proprietary Programs that Drive You Crazy — and Their Open Source Alternatives 01 / 22 / ...